/** * @file sdrv_asw_drv.c * @brief sdrv asw driver source. * * @copyright Copyright (c) 2022 Semidrive Semiconductor. * All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #define LUT_HSIZE_MAX 35 #define LUT_VSIZE_MAX 35 int tblut_ext[LUT_HSIZE_MAX * LUT_VSIZE_MAX * 4 * 6] = {0}; static int sharp_addr[2] = {0x30400, 0x305FF}; static int soft_addr[2] = {0x30600, 0x307FF}; static int sharp_coef[33][5] = { {0, 0, 32, 0, 0}, {0, 0, 32, 0, 0}, {0, -1, 32, 1, 0}, {0, -1, 32, 1, 0}, {0, -1, 32, 1, 0}, {0, -1, 31, 2, 0}, {0, -2, 32, 2, 0}, {0, -2, 31, 3, 0}, {0, -2, 31, 3, 0}, {0, -2, 30, 4, 0}, {0, -2, 30, 4, 0}, {0, -2, 29, 5, 0}, {0, -2, 29, 5, 0}, {0, -3, 29, 6, 0}, {0, -3, 29, 6, 0}, {0, -3, 29, 7, -1}, {0, -3, 28, 8, -1}, {0, -3, 28, 8, -1}, {0, -3, 27, 9, -1}, {0, -3, 27, 9, -1}, {0, -3, 26, 10, -1}, {-1, -3, 26, 11, -1}, {-1, -3, 26, 11, -1}, {-1, -3, 25, 12, -1}, {-1, -3, 24, 13, -1}, {-1, -3, 24, 13, -1}, {-1, -3, 23, 14, -1}, {-1, -2, 22, 15, -2}, {-1, -2, 21, 16, -2}, {-1, -2, 21, 16, -2}, {-1, -2, 20, 17, -2}, {-1, -2, 19, 18, -2}, {-1, -2, 19, 18, -2}}; static int soft_coef[33][5] = { {2, 2, 24, 2, 2}, {2, 2, 23, 3, 2}, {2, 2, 23, 3, 2}, {2, 2, 23, 3, 2}, {2, 2, 23, 3, 2}, {2, 2, 22, 4, 2}, {2, 2, 22, 4, 2}, {2, 1, 23, 4, 2}, {2, 1, 23, 4, 2}, {2, 1, 22, 5, 2}, {2, 1, 22, 5, 2}, {2, 1, 22, 5, 2}, {2, 1, 21, 6, 2}, {2, 1, 21, 6, 2}, {2, 1, 21, 6, 2}, {2, 1, 20, 7, 2}, {2, 1, 20, 7, 2}, {2, 1, 20, 7, 2}, {2, 1, 19, 8, 2}, {2, 1, 19, 8, 2}, {2, 1, 18, 9, 2}, {2, 1, 18, 9, 2}, {2, 1, 18, 9, 2}, {2, 1, 17, 10, 2}, {2, 1, 17, 10, 2}, {2, 1, 16, 11, 2}, {2, 1, 16, 11, 2}, {2, 1, 15, 12, 2}, {2, 1, 16, 12, 1}, {2, 1, 16, 12, 1}, {2, 1, 15, 13, 1}, {2, 1, 15, 13, 1}, {2, 1, 14, 14, 1}}; static inline unsigned int reg_value(unsigned int val, unsigned int src, unsigned int shift, unsigned int mask) { return (src & ~mask) | ((val << shift) & mask); } static inline unsigned int gama_read(unsigned long base, unsigned int reg) { return readl(base + reg); } static inline void lb_write(unsigned long base, unsigned int reg, unsigned int value) { writel(value, base + reg); } static inline void gama_write(unsigned long base, unsigned int reg, unsigned int value) { writel(value, base + reg); } static int get_color_chn(int fmt) { switch (fmt) { case FMT_MONOTONIC_8BIT: case FMT_RGB565: case FMT_RGBA5551: case FMT_ARGB1555: case FMT_RGB_YUV888: case FMT_RGBA8888: case FMT_ARGB8888: return 1; case FMT_YUV422_SEMI_U0V0: case FMT_YUV422_SEMI_V0U0: return 2; case FMT_RGB_YUV888_PLANAR: case FMT_YUV422_PLANAR: case FMT_YUV420_PLANAR: return 3; default: ASW_LOG_ERR("fmt [%d] is error", fmt); return -1; } } int get_dst_color_chn(int fmt) { /* FMT_MONOTONIC_8BIT */ /* FMT_RGB565 */ /* FMT_RGBA5551 */ /* FMT_ARGB1555 */ /* FMT_RGB_YUV888 */ /* FMT_YUV422_UYVY */ /* FMT_YUV422_VYUY */ /* FMT_RGBA8888 */ /* FMT_ARGB8888 */ /* FMT_YUV422_YUYV */ /* FMT_YUV422_YVYU */ switch (fmt) { case FMT_MONOTONIC_8BIT: return 1; case FMT_RGB565: case FMT_RGB_YUV888: case FMT_YUV422_UYVY: case FMT_YUV422_VYUY: case FMT_YUV422_YUYV: case FMT_YUV422_YVYU: return 3; case FMT_RGBA5551: case FMT_ARGB1555: case FMT_RGBA8888: case FMT_ARGB8888: return 4; default: ASW_LOG_ERR("fmt [%d] is error", fmt); return -1; } } static int get_src_color_chn(int fmt) { /*SRC FMT support: */ /* FMT_MONOTONIC_8BIT */ /* FMT_RGB_YUV888_PLANAR*/ /* FMT_YUV422_PLANAR */ /* FMT_YUV420_PLANAR */ /* FMT_RGB565 */ /* FMT_RGBA5551 */ /* FMT_ARGB1555 */ /* FMT_RGB_YUV888 */ /* FMT_YUV422_SEMI_U0V0 */ /* FMT_YUV422_SEMI_V0U0 */ /* FMT_RGBA8888 */ /* FMT_ARGB8888 */ switch (fmt) { case FMT_MONOTONIC_8BIT: return 1; case FMT_RGB565: case FMT_YUV420_PLANAR: case FMT_YUV422_PLANAR: case FMT_RGB_YUV888: case FMT_RGB_YUV888_PLANAR: case FMT_YUV422_SEMI_U0V0: case FMT_YUV422_SEMI_V0U0: return 3; case FMT_RGBA5551: case FMT_ARGB1555: case FMT_RGBA8888: case FMT_ARGB8888: return 4; default: ASW_LOG_ERR("fmt [%d] is error", fmt); return -1; } } static int get_cache_entry_vsize(int type) { switch (type) { case C_ENTRY_TYPE_8X4: case C_ENTRY_TYPE_16X4: case C_ENTRY_TYPE_32X4: return 4; case C_ENTRY_TYPE_8X8: case C_ENTRY_TYPE_16X8: return 8; default: ASW_LOG_ERR("type [%d] is error", type); return -1; } } int get_cache_entry_hsize(int type) { switch (type) { case C_ENTRY_TYPE_8X4: case C_ENTRY_TYPE_8X8: return 8; case C_ENTRY_TYPE_16X4: case C_ENTRY_TYPE_16X8: return 16; case C_ENTRY_TYPE_32X4: return 32; default: ASW_LOG_ERR("type [%d] is error", type); return -1; } } static int get_fmt_h_half(int fmt) { switch (fmt) { case FMT_YUV422_PLANAR: case FMT_YUV420_PLANAR: case FMT_YUV422_SEMI_U0V0: case FMT_YUV422_SEMI_V0U0: return 1; default: return 0; } } static int get_cache_chn_size(struct asw_dev *dev, int index) { int hsize, ce_vsize; switch (index) { default: case 0: hsize = ((dev->input->src.src_hsize + 111) / 128) * 128 + 16; break; case 1: case 2: if (get_fmt_h_half(dev->input->src.src_fmt)) hsize = ((dev->input->src.src_hsize / 2 + 111) / 128) * 128 + 16; else hsize = ((dev->input->src.src_hsize + 111) / 128) * 128 + 16; break; } ce_vsize = get_cache_entry_vsize(dev->input->cache_entry_type); return hsize * ce_vsize * dev->input->cache_way_n; } /*burst_len = tile_hsize * byte_per_pixel / 8*/ /*Using this func can get the byte_per_pixel*/ int get_rdma_bpp_by_fmt(int fmt) { switch (fmt) { case FMT_MONOTONIC_8BIT: case FMT_YUV422_PLANAR: case FMT_YUV420_PLANAR: case FMT_RGB_YUV888_PLANAR: return 1; case FMT_RGB565: case FMT_RGBA5551: case FMT_ARGB1555: case FMT_YUV422_SEMI_U0V0: case FMT_YUV422_SEMI_V0U0: return 2; case FMT_RGB_YUV888: return 3; case FMT_RGBA8888: case FMT_ARGB8888: return 4; default: return 1; } } static void lb_component_ba_calc(struct asw_dev *dev) { int chn, dchn, lut_shape_size, frb_size, cache_chn_size; struct asw_ba_info *bas = &dev->bas; struct asw_input *input = dev->input; if (dev->input->lut_mode == LUT_MODE_CUBIC_SPLINE) { /*LUT*/ bas->asw_pos_lut_ba = GAMA_LB_JUMP; chn = get_color_chn(input->src.src_fmt); lut_shape_size = 35 * 35 * 2 * chn * 4; bas->asw_m_v_ba = bas->asw_pos_lut_ba + lut_shape_size; /*pfile*/ bas->asw_pos_calc_pfile_ba = bas->asw_pos_lut_ba + lut_shape_size * 2; /*alpha[]*/ bas->asw_alpha_ba = bas->asw_pos_calc_pfile_ba + 16 * 4; /*y/step_y*/ bas->asw_y_stepy_ba = bas->asw_alpha_ba + 35 * 4; /*LUT_H[]*/ bas->asw_lut_h_ba = bas->asw_y_stepy_ba + 60 * 4; /*M_H[]*/ bas->asw_m_h_ba = bas->asw_lut_h_ba + 35 * 4; /*Filter Result Buffer*/ bas->asw_frb_ba = ALIGN(bas->asw_m_h_ba + 35 * 4, 16); } else { /*LUT_MODE_BILINEAR*/ bas->asw_frb_ba = GAMA_LB_JUMP; } /*CACHE*/ dchn = get_src_color_chn(input->src.src_fmt); frb_size = (ALIGN(dev->input->dst.dst_hsize, 16) / 4) * 2 * dchn * 4; /*argb*/ bas->asw_cache_ry_ba = ALIGN(bas->asw_frb_ba + frb_size, 128); cache_chn_size = get_cache_chn_size(dev, 0); if ((input->src.src_fmt == FMT_YUV422_SEMI_U0V0) || ((input->src.src_fmt == FMT_YUV422_SEMI_V0U0))) { bas->asw_cache_gu_ba = bas->asw_cache_ry_ba + ALIGN(cache_chn_size, 128); cache_chn_size = get_cache_chn_size(dev, 1); bas->asw_cache_bv_ba = bas->asw_cache_gu_ba + ALIGN(cache_chn_size, 128) + 64; } else { bas->asw_cache_gu_ba = bas->asw_cache_ry_ba + ALIGN(cache_chn_size, 128) + 32; cache_chn_size = get_cache_chn_size(dev, 1); bas->asw_cache_bv_ba = bas->asw_cache_gu_ba + ALIGN(cache_chn_size, 128) + 32; } cache_chn_size = get_cache_chn_size(dev, 2); bas->asw_cache_a_ba = bas->asw_cache_bv_ba + ALIGN(cache_chn_size, 128) + 32; ASW_LOG_DEBUG("asw_pos_calc_pfile_ba = 0x%08x", bas->asw_pos_calc_pfile_ba); ASW_LOG_DEBUG("asw_pos_lut_ba = 0x%08x", bas->asw_pos_lut_ba); ASW_LOG_DEBUG("asw_m_v_ba = 0x%08x", bas->asw_m_v_ba); ASW_LOG_DEBUG("asw_alpha_ba = 0x%08x", bas->asw_alpha_ba); ASW_LOG_DEBUG("asw_y_stepy_ba = 0x%08x", bas->asw_y_stepy_ba); ASW_LOG_DEBUG("asw_lut_h_ba = 0x%08x", bas->asw_lut_h_ba); ASW_LOG_DEBUG("asw_m_h_ba = 0x%08x", bas->asw_m_h_ba); ASW_LOG_DEBUG("asw_frb_ba = 0x%08x", bas->asw_frb_ba); ASW_LOG_DEBUG("asw_cache_ry_ba = 0x%08x", bas->asw_cache_ry_ba); ASW_LOG_DEBUG("asw_cache_gu_ba = 0x%08x", bas->asw_cache_gu_ba); ASW_LOG_DEBUG("asw_cache_bv_ba = 0x%08x", bas->asw_cache_bv_ba); ASW_LOG_DEBUG("asw_cache_a_ba = 0x%08x", bas->asw_cache_a_ba); } static void load_lut(struct asw_dev *dev) { unsigned long base = dev->base; int addr; addr = dev->bas.asw_pos_lut_ba; for (int i = 0; addr < dev->bas.asw_pos_calc_pfile_ba; i++) { lb_write(base, addr, *(unsigned int *)(dev->input->cubic.lut_src_ba + i * 4)); addr += 4; } } static void load_cfg_parameter(struct asw_dev *dev) { unsigned long base = dev->base; int addr; addr = dev->bas.asw_pos_calc_pfile_ba; ASW_LOG_INFO("addr = 0x%x", addr); /*params[0] = (float)1/2*/ lb_write(base, addr, 0x3f000000); addr += 4; /*params[1] = (float)1/3*/ lb_write(base, addr, 0x3eaaaa9f); addr += 4; /*params[2] = (float)1/6*/ lb_write(base, addr, 0x3e2aaac1); addr += 4; /*params[3] = (float)2*/ lb_write(base, addr, 0x40000000); addr += 4; /*params[4] = (float)6*/ lb_write(base, addr, 0x40c00000); addr += 4; /*params[5] = (float)(-(2^24-1)*256)*/ lb_write(base, addr, 0xcf7fffff); addr += 4; /*params[6] = (float)(+(2^24-1)*256)*/ lb_write(base, addr, 0x4f7fffff); addr += 4; /*params[7] = (float)256*/ lb_write(base, addr, 0x43800000); addr += 4; /*params[8]*/ lb_write(base, addr, dev->bas.asw_alpha_ba - GAMA_LB_JUMP); addr += 4; /*params[9]*/ addr += 4; /*params[10]*/ lb_write(base, addr, dev->bas.asw_y_stepy_ba - GAMA_LB_JUMP); addr += 4; /*params[11][12]*/ addr += 8; /*params[13]*/ lb_write(base, addr, dev->bas.asw_lut_h_ba - GAMA_LB_JUMP); addr += 4; /*params[14]*/ lb_write(base, addr, dev->bas.asw_m_h_ba - GAMA_LB_JUMP); addr += 4; } static void load_alpha(struct asw_dev *dev) { unsigned long base = dev->base; int addr; addr = dev->bas.asw_alpha_ba; for (int i = 0; addr < dev->bas.asw_y_stepy_ba; i++) { lb_write(base, addr, *(unsigned int *)(dev->input->cubic.alpha_src_ba + i * 4)); addr += 4; } } static void load_y_stepy(struct asw_dev *dev) { unsigned long base = dev->base; int step, addr; step = (dev->input->dst.dst_vsize + 31) / 32; addr = dev->bas.asw_y_stepy_ba; for (int i = 0; i < step; i++) { float val = (float)i / (float)step; int *pos = (int *)(&val); int value = *pos; lb_write(base, addr, value); addr += 4; } } static void gama_rwdma_init(struct asw_dev *dev) { unsigned long base = dev->base; unsigned int val; /*set dma circular buffer mode*/ gama_write(base, ASW_RD01C(0), dev->input->cbuf.low_limit_addr); gama_write(base, ASW_RD020(0), dev->input->cbuf.high_limit_addr); val = reg_value(dev->input->cbuf.range, 0, ASW_SHIFT01_RD024, ASW_MASK01_RD024); val = reg_value(dev->input->cbuf.enable, val, ASW_SHIFT00_RD024, ASW_MASK00_RD024); gama_write(base, ASW_RD024(0), val); gama_write(base, 0x20000, 0x200000); gama_write(base, 0x2000c, 0x200000); } static void gama_asw_set_hwmode(struct asw_dev *dev) { unsigned long base = dev->base; unsigned int val; gama_rwdma_init(dev); /*mode configs*/ val = gama_read(base, ASW_RB010); val = reg_value(1, val, ASW_SHIFT02_RB010, ASW_MASK02_RB010); val = reg_value(LB_LAYOUT_B, val, ASW_SHIFT01_RB010, ASW_MASK01_RB010); val = reg_value(1, val, ASW_SHIFT00_RB010, ASW_MASK00_RB010); gama_write(base, ASW_RB010, val); } static void gama_asw_cfg(struct asw_dev *dev) { unsigned long base = dev->base; unsigned int c_chn; unsigned int val; int asw_lut_hstep, asw_lut_vstep; c_chn = get_color_chn(dev->input->src.src_fmt); /*LUT parameters*/ val = reg_value(dev->input->lut.asw_lut_hsize - 1, 0, ASW_SHIFT00_RA020, ASW_MASK00_RA020); val = reg_value(dev->input->lut.asw_lut_vsize - 1, val, ASW_SHIFT16_RA020, ASW_MASK16_RA020); gama_write(base, ASW_RA020, val); if (dev->input->lut_mode == LUT_MODE_CUBIC_SPLINE) { asw_lut_hstep = (dev->input->dst.dst_hsize + 31) / 32; asw_lut_vstep = (dev->input->dst.dst_vsize + 31) / 32; } else { /*LUT_MODE_BILINEAR*/ asw_lut_hstep = (dev->input->dst.dst_hsize + dev->input->lut.asw_lut_hsize - 2) / (dev->input->lut.asw_lut_hsize - 1); asw_lut_vstep = (dev->input->dst.dst_vsize + dev->input->lut.asw_lut_vsize - 2) / (dev->input->lut.asw_lut_vsize - 1); } val = reg_value(asw_lut_hstep - 1, 0, ASW_SHIFT00_RA024, ASW_MASK00_RA024); val = reg_value(asw_lut_vstep - 1, val, ASW_SHIFT16_RA024, ASW_MASK16_RA024); gama_write(base, ASW_RA024, val); val = 0x100000 / asw_lut_hstep; /*(int)((1/lut_step_h)*2^20)*/ gama_write(base, ASW_RA028, val); val = 0x100000 / asw_lut_vstep; /*(int)((1/lut_step_v)*2^20)*/ gama_write(base, ASW_RA02C, val); if (dev->input->lut_mode == LUT_MODE_CUBIC_SPLINE) { gama_write(base, ASW_RA030, dev->bas.asw_pos_calc_pfile_ba - GAMA_LB_JUMP); int jump = dev->input->lut.asw_lut_hsize * 2 * c_chn * 4; /*jump one line*/ gama_write(base, ASW_RA034, dev->bas.asw_pos_lut_ba + jump - GAMA_LB_JUMP); gama_write(base, ASW_RA038, dev->bas.asw_m_v_ba + jump - GAMA_LB_JUMP); } else { /*LUT_MODE_BILINEAR*/ gama_write(base, ASW_RA090, dev->input->ext.ext_mlut_rx_ba); gama_write(base, ASW_RA0A8, dev->input->ext.ext_mlut_rx_stride - 1); gama_write(base, ASW_RA094, dev->input->ext.ext_mlut_ry_ba); gama_write(base, ASW_RA0AC, dev->input->ext.ext_mlut_ry_stride - 1); if (c_chn > 1) { gama_write(base, ASW_RA098, dev->input->ext.ext_mlut_gx_ba); gama_write(base, ASW_RA0B0, dev->input->ext.ext_mlut_gx_stride - 1); gama_write(base, ASW_RA09C, dev->input->ext.ext_mlut_gy_ba); gama_write(base, ASW_RA0B4, dev->input->ext.ext_mlut_gy_stride - 1); } if (c_chn > 2) { gama_write(base, ASW_RA0A0, dev->input->ext.ext_mlut_bx_ba); gama_write(base, ASW_RA0B8, dev->input->ext.ext_mlut_bx_stride - 1); gama_write(base, ASW_RA0A4, dev->input->ext.ext_mlut_by_ba); gama_write(base, ASW_RA0BC, dev->input->ext.ext_mlut_by_stride - 1); } } /*ASW Cache parameters*/ gama_write(base, ASW_RA040, dev->bas.asw_cache_ry_ba - GAMA_LB_JUMP); gama_write(base, ASW_RA044, dev->bas.asw_cache_gu_ba - GAMA_LB_JUMP); gama_write(base, ASW_RA048, dev->bas.asw_cache_bv_ba - GAMA_LB_JUMP); gama_write(base, ASW_RA04C, dev->bas.asw_cache_a_ba - GAMA_LB_JUMP); gama_write(base, ASW_RA050, dev->bas.asw_frb_ba - GAMA_LB_JUMP); gama_write(base, ASW_RA058, ALIGN(dev->input->dst.dst_hsize, 16) - 1); /*src/des image formats*/ val = reg_value(dev->input->src.src_vsize - 1, 0, ASW_SHIFT16_RA010, ASW_MASK16_RA010); val = reg_value(dev->input->src.src_hsize - 1, val, ASW_SHIFT00_RA010, ASW_MASK00_RA010); gama_write(base, ASW_RA010, val); val = reg_value(dev->input->dst.dst_vsize - 1, 0, ASW_SHIFT16_RA014, ASW_MASK16_RA014); val = reg_value(dev->input->dst.dst_hsize - 1, val, ASW_SHIFT00_RA014, ASW_MASK00_RA014); gama_write(base, ASW_RA014, val); val = gama_read(base, ASW_RA018); val = reg_value((dev->input->dst.dst_flip & FLIP_TYPE_HFLIP) ? 1 : 0, val, ASW_SHIFT24_RA018, ASW_MASK24_RA018); val = reg_value((dev->input->dst.dst_flip & FLIP_TYPE_VFLIP) ? 1 : 0, val, ASW_SHIFT25_RA018, ASW_MASK25_RA018); val = reg_value(dev->input->dst.dst_fmt, val, ASW_SHIFT16_RA018, ASW_MASK16_RA018); val = reg_value((dev->input->src.src_flip & FLIP_TYPE_HFLIP) ? 1 : 0, val, ASW_SHIFT08_RA018, ASW_MASK08_RA018); val = reg_value((dev->input->src.src_flip & FLIP_TYPE_VFLIP) ? 1 : 0, val, ASW_SHIFT09_RA018, ASW_MASK09_RA018); val = reg_value(dev->input->src.src_fmt, val, ASW_SHIFT00_RA018, ASW_MASK00_RA018); gama_write(base, ASW_RA018, val); gama_write(base, ASW_RA060, dev->input->src.src_ry_ba); gama_write(base, ASW_RA06C, dev->input->src.src_ry_stride - 1); if (c_chn > 1) { gama_write(base, ASW_RA064, dev->input->src.src_gu_ba); gama_write(base, ASW_RA070, dev->input->src.src_gu_stride - 1); } if (c_chn > 2) { gama_write(base, ASW_RA068, dev->input->src.src_bv_ba); gama_write(base, ASW_RA074, dev->input->src.src_bv_stride - 1); } gama_write(base, ASW_RA080, dev->input->dst.dst_ba); gama_write(base, ASW_RA084, dev->input->dst.dst_stride - 1); /*ohter parameters*/ val = gama_read(base, ASW_RA00C); if (dev->input->adb.dirty) { val = reg_value(dev->input->adb.offset, val, ASW_SHIFT04_RA00C, ASW_MASK04_RA00C); val = reg_value(dev->input->adb.slope, val, ASW_SHIFT00_RA00C, ASW_MASK00_RA00C); } else { val = reg_value(0x18, val, ASW_SHIFT04_RA00C, ASW_MASK04_RA00C); val = reg_value(0x7, val, ASW_SHIFT00_RA00C, ASW_MASK00_RA00C); } gama_write(base, ASW_RA00C, val); gama_write(base, ASW_RA088, dev->input->dst.dst_bg_color); val = gama_read(base, ASW_RA008); val = reg_value(dev->input->lut_mode, val, ASW_SHIFT00_RA008, ASW_MASK00_RA008); if (dev->input->lut_mode == LUT_MODE_BILINEAR) { val = reg_value(dev->input->ext_lut_fmt, val, ASW_SHIFT11_RA008, ASW_MASK11_RA008); } if (dev->input->lut_mode == LUT_MODE_CUBIC_SPLINE) { val = reg_value(CUBIC_MODE_INT_ASM, val, ASW_SHIFT10_RA008, ASW_MASK10_RA008); } val = reg_value(dev->input->work_mode, val, ASW_SHIFT08_RA008, ASW_MASK08_RA008); val = reg_value(dev->input->cache_entry_type, val, ASW_SHIFT01_RA008, ASW_MASK01_RA008); val = reg_value(dev->input->cache_way_n, val, ASW_SHIFT04_RA008, ASW_MASK04_RA008); gama_write(base, ASW_RA008, val); gama_write(base, ASW_RC028, 0xFFE); dev->asw_done = 0; switch (dev->input->work_mode) { case WORK_MODE_M_TO_M: default: gama_write(base, ASW_RA01C, 0x3); /*using prepare shadow load.*/ ASW_LOG_DEBUG("m2m cfg fctrl"); gama_write(base, ASW_RA000, 0x1); /*ASW frame start(when m_to_m mode)*/ break; case WORK_MODE_CSI_HS: val = gama_read(base, ASW_RA008); val = reg_value(dev->input->csi_start_ln, val, ASW_SHIFT20_RA008, ASW_MASK20_RA008); val = reg_value(dev->input->hdsk_mode, val, ASW_SHIFT12_RA008, ASW_MASK12_RA008); gama_write(base, ASW_RA008, val); gama_write(base, ASW_RA01C, 0x3); break; case WORK_MODE_DC_HS: val = gama_read(base, ASW_RA008); val = reg_value(dev->input->hdsk_mode, val, ASW_SHIFT12_RA008, ASW_MASK12_RA008); gama_write(base, ASW_RA008, val); gama_write(base, ASW_RA01C, 0x3); break; case WORK_MODE_CSI_DC_HS: val = gama_read(base, ASW_RA008); val = reg_value(dev->input->csi_start_ln, val, ASW_SHIFT20_RA008, ASW_MASK20_RA008); val = reg_value(dev->input->hdsk_mode, val, ASW_SHIFT12_RA008, ASW_MASK12_RA008); gama_write(base, ASW_RA008, val); gama_write(base, ASW_RA01C, 0x3); break; } } static void gama_fliter_set(struct asw_dev *dev) { unsigned long base = dev->base; unsigned int head, tail; for (int i = 0; i < 33; i++) { head = (sharp_coef[i][0] & 0xff) | ((sharp_coef[i][1] & 0xff) << 8) | ((sharp_coef[i][2] & 0xff) << 16); tail = ((sharp_coef[i][3] & 0xff)) | ((sharp_coef[i][4] & 0xff) << 8); gama_write(base, sharp_addr[0] + (i * 2) * 4, head); gama_write(base, sharp_addr[0] + (i * 2 + 1) * 4, tail); } for (int i = 0; i < 33; i++) { head = (soft_coef[i][0] & 0xff) | ((soft_coef[i][1] & 0xff) << 8) | ((soft_coef[i][2] & 0xff) << 16); tail = ((soft_coef[i][3] & 0xff)) | ((soft_coef[i][4] & 0xff) << 8); gama_write(base, soft_addr[0] + (i * 2) * 4, head); gama_write(base, soft_addr[0] + (i * 2 + 1) * 4, tail); } } static void asw_soft_reset(struct asw_dev *dev) { unsigned long base = dev->base; gama_write(base, ASW_RA004, 1); udelay(10); gama_write(base, ASW_RA004, 0); } /*cubic spline*/ static void asw_cubic(struct asw_dev *dev) { lb_component_ba_calc(dev); gama_asw_set_hwmode(dev); load_lut(dev); load_cfg_parameter(dev); load_alpha(dev); load_y_stepy(dev); gama_fliter_set(dev); gama_asw_cfg(dev); } static void asw_cubic_with_hvkt(struct asw_dev *dev, struct hvkt_param *hvkt) { lb_component_ba_calc(dev); gama_asw_set_hwmode(dev); hvkt->lut_addr = dev->base + dev->bas.asw_pos_lut_ba; hvkt->m_v_addr = dev->base + dev->bas.asw_m_v_ba; hvkt->alpha_addr = dev->base + dev->bas.asw_alpha_ba; hvkt->lut_h_step = (dev->input->dst.dst_hsize + (dev->input->lut.asw_lut_hsize - 2)) / (dev->input->lut.asw_lut_hsize - 1); hvkt->lut_v_step = (dev->input->dst.dst_vsize + (dev->input->lut.asw_lut_vsize - 2)) / (dev->input->lut.asw_lut_vsize - 1); lut_hvk_ops.lut_table_gen(hvkt); lut_hvk_ops.lut_m_v_gen(hvkt); load_cfg_parameter(dev); load_y_stepy(dev); gama_fliter_set(dev); gama_asw_cfg(dev); } /*bilinear*/ static void asw_bilinear(struct asw_dev *dev) { lb_component_ba_calc(dev); gama_asw_set_hwmode(dev); gama_fliter_set(dev); gama_asw_cfg(dev); } static void asw_bilinear_with_hvkt(struct asw_dev *dev, struct hvkt_param *hvkt) { lb_component_ba_calc(dev); gama_asw_set_hwmode(dev); hvkt->lut_addr = (int)tblut_ext; hvkt->lut_real_addr[0] = dev->input->ext.ext_mlut_rx_ba; hvkt->lut_real_addr[1] = dev->input->ext.ext_mlut_ry_ba; hvkt->lut_real_addr[2] = dev->input->ext.ext_mlut_gx_ba; hvkt->lut_real_addr[3] = dev->input->ext.ext_mlut_gy_ba; hvkt->lut_real_addr[4] = dev->input->ext.ext_mlut_bx_ba; hvkt->lut_real_addr[5] = dev->input->ext.ext_mlut_by_ba; hvkt->lut_h_step = (dev->input->dst.dst_hsize + (dev->input->lut.asw_lut_hsize - 2)) / (dev->input->lut.asw_lut_hsize - 1); hvkt->lut_v_step = (dev->input->dst.dst_vsize + (dev->input->lut.asw_lut_vsize - 2)) / (dev->input->lut.asw_lut_vsize - 1); lut_hvk_ops.lut_table_gen(hvkt); gama_fliter_set(dev); gama_asw_cfg(dev); } static int asw_irq_handler(unsigned int irq, void *data) { struct asw_dev *dev = (struct asw_dev *)data; unsigned int val; val = gama_read(dev->base, ASW_RC024); gama_write(dev->base, ASW_RC030, val); if (val & WRITE_OUT_FRM_DONE_MASK) { dev->asw_done = 1; #if CONFIG_OS_FREERTOS xSemaphoreGiveFromISR(dev->wdone_sema, NULL); #endif } return 0; } static void asw_cubic_rotation(struct asw_dev *dev, double rotate_angle, struct hvkt_param *hvkt) { lb_component_ba_calc(dev); gama_asw_set_hwmode(dev); hvkt->lut_addr = dev->base + dev->bas.asw_pos_lut_ba; hvkt->m_v_addr = dev->base + dev->bas.asw_m_v_ba; hvkt->alpha_addr = dev->base + dev->bas.asw_alpha_ba; lut_hvk_ops.lut_rotate_table_gen(rotate_angle, hvkt); lut_hvk_ops.lut_m_v_gen(hvkt); dev->input->dst.dst_flip = hvkt->flip_type; load_cfg_parameter(dev); load_y_stepy(dev); gama_fliter_set(dev); gama_asw_cfg(dev); } static void asw_bilinear_rotation(struct asw_dev *dev, double rotate_angle, struct hvkt_param *hvkt) { lb_component_ba_calc(dev); gama_asw_set_hwmode(dev); hvkt->lut_addr = (int)tblut_ext; hvkt->lut_real_addr[0] = dev->input->ext.ext_mlut_rx_ba; hvkt->lut_real_addr[1] = dev->input->ext.ext_mlut_ry_ba; hvkt->lut_real_addr[2] = dev->input->ext.ext_mlut_gx_ba; hvkt->lut_real_addr[3] = dev->input->ext.ext_mlut_gy_ba; hvkt->lut_real_addr[4] = dev->input->ext.ext_mlut_bx_ba; hvkt->lut_real_addr[5] = dev->input->ext.ext_mlut_by_ba; hvkt->lut_h_step = (dev->input->dst.dst_hsize + (dev->input->lut.asw_lut_hsize - 2)) / (dev->input->lut.asw_lut_hsize - 1); hvkt->lut_v_step = (dev->input->dst.dst_vsize + (dev->input->lut.asw_lut_vsize - 2)) / (dev->input->lut.asw_lut_vsize - 1); lut_hvk_ops.lut_rotate_table_gen(rotate_angle, hvkt); dev->input->dst.dst_flip = hvkt->flip_type; gama_fliter_set(dev); gama_asw_cfg(dev); } struct asw_operations sdrv_asw_ops = { .soft_reset = asw_soft_reset, .cubic_cfg = asw_cubic, .cubic_cfg_with_hvkt = asw_cubic_with_hvkt, .cubic_rotation = asw_cubic_rotation, .bilinear_cfg = asw_bilinear, .bilinear_cfg_with_hvkt = asw_bilinear_with_hvkt, .bilinear_rotation = asw_bilinear_rotation, .irq_handler = asw_irq_handler, };