Lines Matching +full:4 +full:- +full:ch
1 // SPDX-License-Identifier: GPL-2.0
11 #include "dcss-dev.h"
15 #define REPEAT_EN BIT(4)
32 #define Y_UV_BYTE_SWAP BIT(4)
38 #define CHR_BIT_DEPTH_POS 4
39 #define CHR_BIT_DEPTH_MASK GENMASK(5, 4)
90 struct dcss_scaler_ch ch[3]; member
96 #define PSC_BITS_FOR_PHASE 4
103 #define PSC_PHASE_MASK (PSC_NUM_PHASES - 1)
105 #define PSC_Q_ROUND_OFFSET (1 << (PSC_Q_FRACTION - 1))
108 * mult_q() - Performs fixed-point multiplication.
124 * div_q() - Performs fixed-point division.
137 temp -= B / 2; in div_q()
144 * exp_approx_q() - Compute approximation to exp(x) function using Taylor
146 * @x: fixed-point argument of exp function
159 term = mult_q(term, div_q(x, 4 << PSC_Q_FRACTION)); in exp_approx_q()
166 * dcss_scaler_gaussian_filter() - Generate gaussian prototype filter.
167 * @fc_q: fixed-point cutoff frequency normalized to range [0, 1]
185 coef[phase][PSC_NUM_TAPS - 1] = 0; in dcss_scaler_gaussian_filter()
190 mid = (PSC_NUM_PHASES * taps) / 2 - 1; in dcss_scaler_gaussian_filter()
198 g1_q = exp_approx_q(div_q(-PSC_Q_ROUND_OFFSET, in dcss_scaler_gaussian_filter()
205 tap_cnt1--; in dcss_scaler_gaussian_filter()
215 if (((-phase_cnt) & PSC_PHASE_MASK) <= 8) { in dcss_scaler_gaussian_filter()
217 coef[(-phase_cnt) & PSC_PHASE_MASK][tap_idx] = g0_q; in dcss_scaler_gaussian_filter()
222 tap_cnt1--; in dcss_scaler_gaussian_filter()
260 * dcss_scaler_filter_design() - Compute filter coefficients using
287 static void dcss_scaler_write(struct dcss_scaler_ch *ch, u32 val, u32 ofs) in dcss_scaler_write() argument
289 struct dcss_scaler *scl = ch->scl; in dcss_scaler_write()
291 dcss_ctxld_write(scl->ctxld, scl->ctx_id, val, ch->base_ofs + ofs); in dcss_scaler_write()
297 struct dcss_scaler_ch *ch; in dcss_scaler_ch_init_all() local
301 ch = &scl->ch[i]; in dcss_scaler_ch_init_all()
303 ch->base_ofs = scaler_base + i * 0x400; in dcss_scaler_ch_init_all()
305 ch->base_reg = ioremap(ch->base_ofs, SZ_4K); in dcss_scaler_ch_init_all()
306 if (!ch->base_reg) { in dcss_scaler_ch_init_all()
307 dev_err(scl->dev, "scaler: unable to remap ch base\n"); in dcss_scaler_ch_init_all()
308 return -ENOMEM; in dcss_scaler_ch_init_all()
311 ch->scl = scl; in dcss_scaler_ch_init_all()
323 return -ENOMEM; in dcss_scaler_init()
325 dcss->scaler = scaler; in dcss_scaler_init()
326 scaler->dev = dcss->dev; in dcss_scaler_init()
327 scaler->ctxld = dcss->ctxld; in dcss_scaler_init()
328 scaler->ctx_id = CTX_SB_HP; in dcss_scaler_init()
334 if (scaler->ch[i].base_reg) in dcss_scaler_init()
335 iounmap(scaler->ch[i].base_reg); in dcss_scaler_init()
340 return -ENOMEM; in dcss_scaler_init()
351 struct dcss_scaler_ch *ch = &scl->ch[ch_no]; in dcss_scaler_exit() local
353 dcss_writel(0, ch->base_reg + DCSS_SCALER_CTRL); in dcss_scaler_exit()
355 if (ch->base_reg) in dcss_scaler_exit()
356 iounmap(ch->base_reg); in dcss_scaler_exit()
364 struct dcss_scaler_ch *ch = &scl->ch[ch_num]; in dcss_scaler_ch_enable() local
370 dcss_scaler_write(ch, ch->sdata_ctrl, DCSS_SCALER_SDATA_CTRL); in dcss_scaler_ch_enable()
372 if (ch->scaler_ctrl != scaler_ctrl) in dcss_scaler_ch_enable()
373 ch->scaler_ctrl_chgd = true; in dcss_scaler_ch_enable()
375 ch->scaler_ctrl = scaler_ctrl; in dcss_scaler_ch_enable()
378 static void dcss_scaler_yuv_enable(struct dcss_scaler_ch *ch, bool en) in dcss_scaler_yuv_enable() argument
380 ch->sdata_ctrl &= ~YUV_EN; in dcss_scaler_yuv_enable()
381 ch->sdata_ctrl |= en ? YUV_EN : 0; in dcss_scaler_yuv_enable()
384 static void dcss_scaler_rtr_8lines_enable(struct dcss_scaler_ch *ch, bool en) in dcss_scaler_rtr_8lines_enable() argument
386 ch->sdata_ctrl &= ~RTRAM_8LINES; in dcss_scaler_rtr_8lines_enable()
387 ch->sdata_ctrl |= en ? RTRAM_8LINES : 0; in dcss_scaler_rtr_8lines_enable()
390 static void dcss_scaler_bit_depth_set(struct dcss_scaler_ch *ch, int depth) in dcss_scaler_bit_depth_set() argument
396 dcss_scaler_write(ch, in dcss_scaler_bit_depth_set()
413 PSC_LOC_HORZ_0_VERT_1_OVER_2 = 4,
417 static void dcss_scaler_format_set(struct dcss_scaler_ch *ch, in dcss_scaler_format_set() argument
421 dcss_scaler_write(ch, src_fmt, DCSS_SCALER_SRC_FORMAT); in dcss_scaler_format_set()
422 dcss_scaler_write(ch, dst_fmt, DCSS_SCALER_DST_FORMAT); in dcss_scaler_format_set()
425 static void dcss_scaler_res_set(struct dcss_scaler_ch *ch, in dcss_scaler_res_set() argument
457 /* for 4:4:4 to 4:2:2 conversion, source height should be 1 less */ in dcss_scaler_res_set()
459 lsrc_yres--; in dcss_scaler_res_set()
460 csrc_yres--; in dcss_scaler_res_set()
463 dcss_scaler_write(ch, (((lsrc_yres - 1) << HEIGHT_POS) & HEIGHT_MASK) | in dcss_scaler_res_set()
464 (((lsrc_xres - 1) << WIDTH_POS) & WIDTH_MASK), in dcss_scaler_res_set()
466 dcss_scaler_write(ch, (((csrc_yres - 1) << HEIGHT_POS) & HEIGHT_MASK) | in dcss_scaler_res_set()
467 (((csrc_xres - 1) << WIDTH_POS) & WIDTH_MASK), in dcss_scaler_res_set()
469 dcss_scaler_write(ch, (((ldst_yres - 1) << HEIGHT_POS) & HEIGHT_MASK) | in dcss_scaler_res_set()
470 (((ldst_xres - 1) << WIDTH_POS) & WIDTH_MASK), in dcss_scaler_res_set()
472 dcss_scaler_write(ch, (((cdst_yres - 1) << HEIGHT_POS) & HEIGHT_MASK) | in dcss_scaler_res_set()
473 (((cdst_xres - 1) << WIDTH_POS) & WIDTH_MASK), in dcss_scaler_res_set()
489 static void dcss_scaler_fractions_set(struct dcss_scaler_ch *ch, in dcss_scaler_fractions_set() argument
515 * (1/4 chroma input line spacing) in dcss_scaler_fractions_set()
517 c_vstart -= (1 << (PSC_PHASE_FRACTION_BITS - 2)); in dcss_scaler_fractions_set()
525 c_vstart -= (1 << (PSC_PHASE_FRACTION_BITS - 1)); in dcss_scaler_fractions_set()
535 /* move chroma left 1/4 chroma input sample spacing */ in dcss_scaler_fractions_set()
536 c_hstart -= (1 << (PSC_PHASE_FRACTION_BITS - 2)); in dcss_scaler_fractions_set()
560 ch->c_vstart = c_vstart; in dcss_scaler_fractions_set()
561 ch->c_hstart = c_hstart; in dcss_scaler_fractions_set()
563 dcss_scaler_write(ch, 0, DCSS_SCALER_V_LUM_START); in dcss_scaler_fractions_set()
564 dcss_scaler_write(ch, l_vinc, DCSS_SCALER_V_LUM_INC); in dcss_scaler_fractions_set()
566 dcss_scaler_write(ch, 0, DCSS_SCALER_H_LUM_START); in dcss_scaler_fractions_set()
567 dcss_scaler_write(ch, l_hinc, DCSS_SCALER_H_LUM_INC); in dcss_scaler_fractions_set()
569 dcss_scaler_write(ch, c_vstart, DCSS_SCALER_V_CHR_START); in dcss_scaler_fractions_set()
570 dcss_scaler_write(ch, c_vinc, DCSS_SCALER_V_CHR_INC); in dcss_scaler_fractions_set()
572 dcss_scaler_write(ch, c_hstart, DCSS_SCALER_H_CHR_START); in dcss_scaler_fractions_set()
573 dcss_scaler_write(ch, c_hinc, DCSS_SCALER_H_CHR_INC); in dcss_scaler_fractions_set()
585 static void dcss_scaler_program_5_coef_set(struct dcss_scaler_ch *ch, in dcss_scaler_program_5_coef_set() argument
592 dcss_scaler_write(ch, ((coef[i][1] & 0xfff) << 16 | in dcss_scaler_program_5_coef_set()
593 (coef[i][2] & 0xfff) << 4 | in dcss_scaler_program_5_coef_set()
596 dcss_scaler_write(ch, ((coef[i][3] & 0x0ff) << 20 | in dcss_scaler_program_5_coef_set()
597 (coef[i][4] & 0xfff) << 8 | in dcss_scaler_program_5_coef_set()
598 (coef[i][5] & 0xff0) >> 4), in dcss_scaler_program_5_coef_set()
600 dcss_scaler_write(ch, ((coef[i][5] & 0x00f) << 24), in dcss_scaler_program_5_coef_set()
605 for (phase = (PSC_NUM_PHASES >> 1) - 1; in dcss_scaler_program_5_coef_set()
606 i < PSC_NUM_PHASES; i++, phase--) { in dcss_scaler_program_5_coef_set()
607 dcss_scaler_write(ch, ((coef[phase][5] & 0xfff) << 16 | in dcss_scaler_program_5_coef_set()
608 (coef[phase][4] & 0xfff) << 4 | in dcss_scaler_program_5_coef_set()
611 dcss_scaler_write(ch, ((coef[phase][3] & 0x0ff) << 20 | in dcss_scaler_program_5_coef_set()
613 (coef[phase][1] & 0xff0) >> 4), in dcss_scaler_program_5_coef_set()
615 dcss_scaler_write(ch, ((coef[phase][1] & 0x00f) << 24), in dcss_scaler_program_5_coef_set()
620 static void dcss_scaler_program_7_coef_set(struct dcss_scaler_ch *ch, in dcss_scaler_program_7_coef_set() argument
627 dcss_scaler_write(ch, ((coef[i][0] & 0xfff) << 16 | in dcss_scaler_program_7_coef_set()
628 (coef[i][1] & 0xfff) << 4 | in dcss_scaler_program_7_coef_set()
631 dcss_scaler_write(ch, ((coef[i][2] & 0x0ff) << 20 | in dcss_scaler_program_7_coef_set()
633 (coef[i][4] & 0xff0) >> 4), in dcss_scaler_program_7_coef_set()
635 dcss_scaler_write(ch, ((coef[i][4] & 0x00f) << 24 | in dcss_scaler_program_7_coef_set()
642 for (phase = (PSC_NUM_PHASES >> 1) - 1; in dcss_scaler_program_7_coef_set()
643 i < PSC_NUM_PHASES; i++, phase--) { in dcss_scaler_program_7_coef_set()
644 dcss_scaler_write(ch, ((coef[phase][6] & 0xfff) << 16 | in dcss_scaler_program_7_coef_set()
645 (coef[phase][5] & 0xfff) << 4 | in dcss_scaler_program_7_coef_set()
646 (coef[phase][4] & 0xf00) >> 8), in dcss_scaler_program_7_coef_set()
648 dcss_scaler_write(ch, ((coef[phase][4] & 0x0ff) << 20 | in dcss_scaler_program_7_coef_set()
650 (coef[phase][2] & 0xff0) >> 4), in dcss_scaler_program_7_coef_set()
652 dcss_scaler_write(ch, ((coef[phase][2] & 0x00f) << 24 | in dcss_scaler_program_7_coef_set()
659 static void dcss_scaler_yuv_coef_set(struct dcss_scaler_ch *ch, in dcss_scaler_yuv_coef_set() argument
674 ch->use_nn_interpolation); in dcss_scaler_yuv_coef_set()
675 dcss_scaler_program_7_coef_set(ch, DCSS_SCALER_COEF_HLUM, coef); in dcss_scaler_yuv_coef_set()
680 ch->use_nn_interpolation); in dcss_scaler_yuv_coef_set()
683 dcss_scaler_program_5_coef_set(ch, DCSS_SCALER_COEF_VLUM, coef); in dcss_scaler_yuv_coef_set()
685 dcss_scaler_program_7_coef_set(ch, DCSS_SCALER_COEF_VLUM, coef); in dcss_scaler_yuv_coef_set()
699 (src_xres == dst_xres) && (ch->c_hstart == 0), in dcss_scaler_yuv_coef_set()
700 coef, ch->use_nn_interpolation); in dcss_scaler_yuv_coef_set()
702 dcss_scaler_program_7_coef_set(ch, DCSS_SCALER_COEF_HCHR, coef); in dcss_scaler_yuv_coef_set()
706 (src_yres == dst_yres) && (ch->c_vstart == 0), in dcss_scaler_yuv_coef_set()
707 coef, ch->use_nn_interpolation); in dcss_scaler_yuv_coef_set()
709 dcss_scaler_program_5_coef_set(ch, DCSS_SCALER_COEF_VCHR, coef); in dcss_scaler_yuv_coef_set()
711 dcss_scaler_program_7_coef_set(ch, DCSS_SCALER_COEF_VCHR, coef); in dcss_scaler_yuv_coef_set()
714 static void dcss_scaler_rgb_coef_set(struct dcss_scaler_ch *ch, in dcss_scaler_rgb_coef_set() argument
723 ch->use_nn_interpolation); in dcss_scaler_rgb_coef_set()
724 dcss_scaler_program_7_coef_set(ch, DCSS_SCALER_COEF_HLUM, coef); in dcss_scaler_rgb_coef_set()
729 ch->use_nn_interpolation); in dcss_scaler_rgb_coef_set()
730 dcss_scaler_program_7_coef_set(ch, DCSS_SCALER_COEF_VLUM, coef); in dcss_scaler_rgb_coef_set()
733 static void dcss_scaler_set_rgb10_order(struct dcss_scaler_ch *ch, in dcss_scaler_set_rgb10_order() argument
738 if (format->is_yuv) in dcss_scaler_set_rgb10_order()
741 ch->sdata_ctrl &= ~A2R10G10B10_FORMAT_MASK; in dcss_scaler_set_rgb10_order()
743 if (format->depth != 30) in dcss_scaler_set_rgb10_order()
746 switch (format->format) { in dcss_scaler_set_rgb10_order()
772 ch->sdata_ctrl |= a2r10g10b10_format << A2R10G10B10_FORMAT_POS; in dcss_scaler_set_rgb10_order()
778 struct dcss_scaler_ch *ch = &scl->ch[ch_num]; in dcss_scaler_set_filter() local
780 ch->use_nn_interpolation = scaling_filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR; in dcss_scaler_set_filter()
788 struct dcss_scaler_ch *ch = &scl->ch[ch_num]; in dcss_scaler_setup() local
794 u32 pix_format = format->format; in dcss_scaler_setup()
796 if (format->is_yuv) { in dcss_scaler_setup()
797 dcss_scaler_yuv_enable(ch, true); in dcss_scaler_setup()
812 dcss_scaler_yuv_enable(ch, false); in dcss_scaler_setup()
814 pixel_depth = format->depth; in dcss_scaler_setup()
817 dcss_scaler_fractions_set(ch, src_xres, src_yres, dst_xres, in dcss_scaler_setup()
821 if (format->is_yuv) in dcss_scaler_setup()
822 dcss_scaler_yuv_coef_set(ch, src_format, dst_format, in dcss_scaler_setup()
826 dcss_scaler_rgb_coef_set(ch, src_xres, src_yres, in dcss_scaler_setup()
829 dcss_scaler_rtr_8lines_enable(ch, rtr_8line_en); in dcss_scaler_setup()
830 dcss_scaler_bit_depth_set(ch, pixel_depth); in dcss_scaler_setup()
831 dcss_scaler_set_rgb10_order(ch, format); in dcss_scaler_setup()
832 dcss_scaler_format_set(ch, src_format, dst_format); in dcss_scaler_setup()
833 dcss_scaler_res_set(ch, src_xres, src_yres, dst_xres, dst_yres, in dcss_scaler_setup()
842 dcss_ctxld_assert_locked(scl->ctxld); in dcss_scaler_write_sclctrl()
845 struct dcss_scaler_ch *ch = &scl->ch[chnum]; in dcss_scaler_write_sclctrl() local
847 if (ch->scaler_ctrl_chgd) { in dcss_scaler_write_sclctrl()
848 dcss_ctxld_write_irqsafe(scl->ctxld, scl->ctx_id, in dcss_scaler_write_sclctrl()
849 ch->scaler_ctrl, in dcss_scaler_write_sclctrl()
850 ch->base_ofs + in dcss_scaler_write_sclctrl()
852 ch->scaler_ctrl_chgd = false; in dcss_scaler_write_sclctrl()