clk_prepare_enable(lcdc_dev->hclk);
clk_prepare_enable(lcdc_dev->dclk);
clk_prepare_enable(lcdc_dev->aclk);
- /*clk_prepare_enable(lcdc_dev->pd);*/
+ clk_prepare_enable(lcdc_dev->pd);
spin_lock(&lcdc_dev->reg_lock);
lcdc_dev->clk_on = 1;
spin_unlock(&lcdc_dev->reg_lock);
clk_disable_unprepare(lcdc_dev->dclk);
clk_disable_unprepare(lcdc_dev->hclk);
clk_disable_unprepare(lcdc_dev->aclk);
- /*clk_disable_unprepare(lcdc_dev->pd);*/
+ clk_disable_unprepare(lcdc_dev->pd);
}
return 0;
lcdc_dev->hclk = devm_clk_get(lcdc_dev->dev, "hclk_lcdc");
lcdc_dev->aclk = devm_clk_get(lcdc_dev->dev, "aclk_lcdc");
lcdc_dev->dclk = devm_clk_get(lcdc_dev->dev, "dclk_lcdc");
- /*lcdc_dev->pd = devm_clk_get(lcdc_dev->dev, "pd_lcdc");*/
+ lcdc_dev->pd = devm_clk_get(lcdc_dev->dev, "pd_lcdc");
- if (/*IS_ERR(lcdc_dev->pd) || */(IS_ERR(lcdc_dev->aclk)) ||
+ if (IS_ERR(lcdc_dev->pd) || (IS_ERR(lcdc_dev->aclk)) ||
(IS_ERR(lcdc_dev->dclk)) || (IS_ERR(lcdc_dev->hclk))) {
dev_err(lcdc_dev->dev, "failed to get lcdc%d clk source\n",
lcdc_dev->id);
lcdc_grf_writel(lcdc_dev->pmugrf_base,
PMUGRF_SOC_CON0_VOP, v);
}
+#if 0
lcdc_writel(lcdc_dev, CABC_GAUSS_LINE0_0, 0x15110903);
lcdc_writel(lcdc_dev, CABC_GAUSS_LINE0_1, 0x00030911);
lcdc_writel(lcdc_dev, CABC_GAUSS_LINE1_0, 0x1a150b04);
lcdc_writel(lcdc_dev, CABC_GAUSS_LINE1_1, 0x00040b15);
lcdc_writel(lcdc_dev, CABC_GAUSS_LINE2_0, 0x15110903);
lcdc_writel(lcdc_dev, CABC_GAUSS_LINE2_1, 0x00030911);
-
+#else
+ lcdc_writel(lcdc_dev, CABC_GAUSS_LINE0_0, 0x40000000);
+ lcdc_writel(lcdc_dev, CABC_GAUSS_LINE0_1, 0x0);
+ lcdc_writel(lcdc_dev, CABC_GAUSS_LINE1_0, 0x80000000);
+ lcdc_writel(lcdc_dev, CABC_GAUSS_LINE1_1, 0x0);
+ lcdc_writel(lcdc_dev, CABC_GAUSS_LINE2_0, 0x40000000);
+ lcdc_writel(lcdc_dev, CABC_GAUSS_LINE2_1, 0x0);
+#endif
lcdc_writel(lcdc_dev, FRC_LOWER01_0, 0x12844821);
lcdc_writel(lcdc_dev, FRC_LOWER01_1, 0x21488412);
lcdc_writel(lcdc_dev, FRC_LOWER10_0, 0xa55a9696);
u16 post_dsp_vact_st_f1, post_dsp_vact_end_f1;
u16 post_h_fac, post_v_fac;
+ screen->post_dsp_stx = x_res * (100 - dev_drv->overscan.left) / 200;
+ screen->post_dsp_sty = y_res * (100 - dev_drv->overscan.top) / 200;
+ screen->post_xsize = x_res *
+ (dev_drv->overscan.left + dev_drv->overscan.right) / 200;
+ screen->post_ysize = y_res *
+ (dev_drv->overscan.top + dev_drv->overscan.bottom) / 200;
+
h_total = screen->mode.hsync_len + screen->mode.left_margin +
x_res + screen->mode.right_margin;
v_total = screen->mode.vsync_len + screen->mode.upper_margin +
for (i = 0; i < win->area_num; i++) {
ppixel_alpha |= ((win->area[i].format == ARGB888) ||
(win->area[i].format == FBDC_ARGB_888) ||
+ (win->area[i].format == FBDC_ABGR_888) ||
(win->area[i].format == ABGR888)) ? 1 : 0;
}
global_alpha = (win->g_alpha_val == 0) ? 0 : 1;
}
mask = m_WIN0_EN | m_WIN0_DATA_FMT | m_WIN0_FMT_10 |
m_WIN0_LB_MODE | m_WIN0_RB_SWAP | m_WIN0_X_MIRROR |
- m_WIN0_Y_MIRROR | m_WIN0_CSC_MODE;
+ m_WIN0_Y_MIRROR | m_WIN0_CSC_MODE |m_WIN0_UV_SWAP;
val = v_WIN0_EN(win->state) |
v_WIN0_DATA_FMT(win->area[0].fmt_cfg) |
v_WIN0_FMT_10(win->fmt_10) |
v_WIN0_RB_SWAP(win->area[0].swap_rb) |
v_WIN0_X_MIRROR(win->mirror_en) |
v_WIN0_Y_MIRROR(win->mirror_en) |
- v_WIN0_CSC_MODE(win->csc_mode);
+ v_WIN0_CSC_MODE(win->csc_mode) |
+ v_WIN0_UV_SWAP(win->area[0].swap_uv);
lcdc_msk_reg(lcdc_dev, WIN0_CTRL0 + off, mask, val);
mask = m_WIN0_BIC_COE_SEL |
int timeout;
unsigned long flags;
- spin_lock(&lcdc_dev->reg_lock);
if (likely(lcdc_dev->clk_on)) {
lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
v_STANDBY_EN(lcdc_dev->standby));
/*rk3368_lcdc_post_cfg(dev_drv); */
lcdc_cfg_done(lcdc_dev);
}
- spin_unlock(&lcdc_dev->reg_lock);
/*if (dev_drv->wait_fs) { */
if (0) {
h_total = hsync_len + left_margin + x_res + right_margin;
v_total = vsync_len + upper_margin + y_res + lower_margin;
- screen->post_dsp_stx = x_res * (100 - screen->overscan.left) / 200;
- screen->post_dsp_sty = y_res * (100 - screen->overscan.top) / 200;
- screen->post_xsize = x_res *
- (screen->overscan.left + screen->overscan.right) / 200;
- screen->post_ysize = y_res *
- (screen->overscan.top + screen->overscan.bottom) / 200;
-
mask = m_DSP_HS_PW | m_DSP_HTOTAL;
val = v_DSP_HS_PW(hsync_len) | v_DSP_HTOTAL(h_total);
lcdc_msk_reg(lcdc_dev, DSP_HTOTAL_HS_END, mask, val);
else
lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
v_DSP_LUT_EN(1));
- if (screen->cabc_lut == NULL) {
- lcdc_msk_reg(lcdc_dev, CABC_CTRL0, m_CABC_EN,
- v_CABC_EN(0));
- } else {
- lcdc_msk_reg(lcdc_dev, CABC_CTRL1, m_CABC_LUT_EN,
- v_CABC_LUT_EN(1));
- }
rk3368_lcdc_bcsh_path_sel(dev_drv);
rk3368_config_timing(dev_drv);
}
/*rockchip_set_system_status(sys_status);*/
rk3368_lcdc_pre_init(dev_drv);
rk3368_lcdc_clk_enable(lcdc_dev);
+ rk3368_lcdc_enable_irq(dev_drv);
#if defined(CONFIG_ROCKCHIP_IOMMU)
if (dev_drv->iommu_enabled) {
if (!dev_drv->mmu_dev) {
rk3368_lcdc_mmu_en(dev_drv); */
if ((support_uboot_display() && (lcdc_dev->prop == PRMRY))) {
rk3368_lcdc_set_dclk(dev_drv, 0);
- rk3368_lcdc_enable_irq(dev_drv);
+ /*rk3368_lcdc_enable_irq(dev_drv);*/
} else {
rk3368_load_screen(dev_drv, 1);
}
break;
case YUV420:
case YUV420_A:
+ case YUV420_NV21:
cbcr_srcW = srcW / 2;
cbcr_dstW = dstW;
cbcr_srcH = srcH / 2;
/*line buffer mode */
if ((win->area[0].format == YUV422) ||
(win->area[0].format == YUV420) ||
+ (win->area[0].format == YUV420_NV21) ||
(win->area[0].format == YUV422_A) ||
(win->area[0].format == YUV420_A)) {
if (win->cbr_hor_scl_mode == SCALE_DOWN) {
struct rk_screen *screen, struct rk_lcdc_win *win)
{
u32 xact, yact, xvir, yvir, xpos, ypos;
- u8 fmt_cfg = 0, swap_rb;
+ u8 fmt_cfg = 0, swap_rb, swap_uv = 0;
char fmt[9] = "NULL";
xpos = dsp_x_pos(win->mirror_en, screen, &win->area[0]);
win->fmt_10 = 0;
win->area[0].fbdc_fmt_cfg = 0x0c;
break;
+ case FBDC_ABGR_888:
+ fmt_cfg = 0;
+ swap_rb = 1;
+ win->fmt_10 = 0;
+ win->area[0].fbdc_fmt_cfg = 0x0c;
+ break;
case FBDC_RGBX_888:
fmt_cfg = 0;
swap_rb = 0;
swap_rb = 0;
win->fmt_10 = 0;
break;
+ case YUV420_NV21:
+ fmt_cfg = 4;
+ swap_rb = 0;
+ swap_uv = 1;
+ win->fmt_10 = 0;
+ break;
case YUV444:
fmt_cfg = 6;
swap_rb = 0;
}
win->area[0].fmt_cfg = fmt_cfg;
win->area[0].swap_rb = swap_rb;
+ win->area[0].swap_uv = swap_uv;
win->area[0].dsp_stx = xpos;
win->area[0].dsp_sty = ypos;
xact = win->area[0].xact;
win->area[i].dsp_sty =
dsp_y_pos(win->mirror_en, screen,
&win->area[i]);
-
+ if ((win->area[i].xact != win->area[i].xsize) ||
+ (win->area[i].yact != win->area[i].ysize)) {
+ pr_err("win[%d]->area[%d],not support scale\n",
+ win->id, i);
+ pr_err("xact=%d,yact=%d,xsize=%d,ysize=%d\n",
+ win->area[i].xact,win->area[i].yact,
+ win->area[i].xsize,win->area[i].ysize);
+ win->area[i].xsize = win->area[i].xact;
+ win->area[i].ysize = win->area[i].yact;
+ }
DBG(2, "fmt:%s:xsize:%d>>ysize:%d>>xpos:%d>>ypos:%d\n",
get_format_string(win->area[i].format, fmt),
win->area[i].xsize, win->area[i].ysize,
{
struct lcdc_device *lcdc_dev = container_of(dev_drv,
struct lcdc_device, driver);
- /*struct device_node *backlight;*/
+ struct device_node *backlight;
+ struct property *prop;
+ u32 brightness_levels[256];
+ u32 length, max, last;
if (lcdc_dev->backlight)
return 0;
-#if 0
backlight = of_parse_phandle(lcdc_dev->dev->of_node, "backlight", 0);
if (backlight) {
lcdc_dev->backlight = of_find_backlight_by_node(backlight);
} else {
dev_info(lcdc_dev->dev, "No find backlight device node\n");
}
-#endif
+ prop = of_find_property(backlight, "brightness-levels", &length);
+ if (!prop)
+ return -EINVAL;
+ max = length / sizeof(u32);
+ last = max - 1;
+ if (!of_property_read_u32_array(backlight, "brightness-levels", brightness_levels, max)) {
+ if (brightness_levels[0] > brightness_levels[last])
+ dev_drv->cabc_pwm_pol = 1;/*negative*/
+ else
+ dev_drv->cabc_pwm_pol = 0;/*positive*/
+ } else {
+ dev_info(lcdc_dev->dev, "Can not read brightness-levels value\n");
+ }
return 0;
}
static int rk3368_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv, int win_id)
{
- return 0;
+ struct lcdc_device *lcdc_dev =
+ container_of(dev_drv, struct lcdc_device, driver);
+ int win_status = 0;
+ if (win_id == 0)
+ win_status = lcdc_read_bit(lcdc_dev, WIN0_CTRL0, m_WIN0_EN);
+ else if (win_id == 1)
+ win_status = lcdc_read_bit(lcdc_dev, WIN1_CTRL0, m_WIN1_EN);
+ else if (win_id == 2)
+ win_status = lcdc_read_bit(lcdc_dev, WIN2_CTRL0, m_WIN2_EN);
+ else if (win_id == 3)
+ win_status = lcdc_read_bit(lcdc_dev, WIN3_CTRL0, m_WIN3_EN);
+ else if (win_id == 4)
+ win_status = lcdc_read_bit(lcdc_dev, HWC_CTRL0, m_HWC_EN);
+ else
+ pr_err("!!!%s,win_id :%d,unsupport!!!\n",__func__,win_id);
+
+ return win_status;
}
/*overlay will be do at regupdate*/
spin_unlock(&lcdc_dev->reg_lock);
return 0;
}
+static u32 pwm_period_hpr, pwm_duty_lpr;
+static u32 cabc_status = 0;
-static struct lcdc_cabc_mode cabc_mode[4] = {
- /* calc, up, down, global_limit */
- {5, 256, 256, 256}, /*mode 1 0*/
- {5, 258, 253, 277}, /*mode 2 15%*/
- {5, 259, 252, 330}, /*mode 3 40%*/
- {5, 267, 244, 400}, /*mode 4 60%*/
-};
+int rk3368_lcdc_update_pwm(int bl_pwm_period, int bl_pwm_duty)
+{
+ pwm_period_hpr = bl_pwm_period;
+ pwm_duty_lpr = bl_pwm_duty;
+ /*pr_info("bl_pwm_period_hpr = 0x%x, bl_pwm_duty_lpr = 0x%x\n",
+ bl_pwm_period, bl_pwm_duty);*/
+ return 0;
+}
-static int rk3368_lcdc_set_dsp_cabc(struct rk_lcdc_driver *dev_drv, int mode)
+int rk3368_lcdc_cabc_status(void)
+{
+ return cabc_status;
+}
+
+static int rk3368_lcdc_set_dsp_cabc(struct rk_lcdc_driver *dev_drv,
+ int mode, int calc, int up,
+ int down, int global)
{
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
cabc_lut = screen->cabc_lut;
}
+ if (!screen->cabc_gamma_base) {
+ pr_err("screen cabc_gamma_base no config, so not open cabc\n");
+ return 0;
+ }
dev_drv->cabc_mode = mode;
cabc_en = (mode > 0) ? 1 : 0;
-
+ rk3368_lcdc_get_backlight_device(dev_drv);
if (cabc_en == 0) {
spin_lock(&lcdc_dev->reg_lock);
if (lcdc_dev->clk_on) {
m_CABC_EN, v_CABC_EN(0));
lcdc_cfg_done(lcdc_dev);
}
+ pr_info("mode = 0, close cabc\n");
+ rk_pwm_set(pwm_period_hpr, pwm_duty_lpr);
+ cabc_status = 0;
spin_unlock(&lcdc_dev->reg_lock);
return 0;
}
+ if (cabc_status == 0) { /*get from pwm*/
+ rk_pwm_get(&pwm_period_hpr, &pwm_duty_lpr);
+ pr_info("pwm_period_hpr=0x%x, pwm_duty_lpr=0x%x\n",
+ pwm_period_hpr, pwm_duty_lpr);
+ }
total_pixel = screen->mode.xres * screen->mode.yres;
- pixel_num = 1000 - (cabc_mode[mode - 1].pixel_num);
+ pixel_num = 1000 - calc;
calc_pixel = (total_pixel * pixel_num) / 1000;
- stage_up = cabc_mode[mode - 1].stage_up;
- stage_down = cabc_mode[mode - 1].stage_down;
- global_su = cabc_mode[mode - 1].global_su;
+ stage_up = up;
+ stage_down = down;
+ global_su = global;
+ pr_info("enable cabc:mode=%d, calc=%d, up=%d, down=%d, global=%d\n",
+ mode, calc, stage_up, stage_down, global_su);
stage_up_rec = 256 * 256 / stage_up;
stage_down_rec = 256 * 256 / stage_down;
- global_su_rec = (256 * 256 / global_su) - 1;
+ global_su_rec = (256 * 256 / global_su);
gamma_global_su_rec = cabc_lut[global_su_rec];
spin_lock(&lcdc_dev->reg_lock);
lcdc_msk_reg(lcdc_dev, CABC_CTRL3, mask, val);
lcdc_cfg_done(lcdc_dev);
}
+ cabc_status = 1;
spin_unlock(&lcdc_dev->reg_lock);
return 0;
return 0;
}
+static int rk3368_lcdc_set_overscan(struct rk_lcdc_driver *dev_drv,
+ struct overscan *overscan)
+{
+ rk3368_lcdc_post_cfg(dev_drv);
+
+ return 0;
+}
+
static struct rk_lcdc_drv_ops lcdc_drv_ops = {
.open = rk3368_lcdc_open,
.win_direct_en = rk3368_lcdc_win_direct_en,
.dsp_black = rk3368_lcdc_dsp_black,
.backlight_close = rk3368_lcdc_backlight_close,
.mmu_en = rk3368_lcdc_mmu_en,
+ .set_overscan = rk3368_lcdc_set_overscan,
};
#ifdef LCDC_IRQ_EMPTY_DEBUG
struct lcdc_device *lcdc_dev = (struct lcdc_device *)dev_id;
ktime_t timestamp = ktime_get();
u32 intr_status;
-
+ u32 scale_global_limit, scale_global_limit_reg;
+ u32 cabc_pwm_lut_value;
+ int pwm_plus;
+ int *cabc_gamma_base = NULL;
intr_status = lcdc_readl(lcdc_dev, INTR_STATUS);
if (intr_status & m_FS_INTR_STS) {
#endif
lcdc_dev->driver.vsync_info.timestamp = timestamp;
wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
-
} else if (intr_status & m_LINE_FLAG0_INTR_STS) {
lcdc_dev->driver.frame_time.last_framedone_t =
- lcdc_dev->driver.frame_time.framedone_t;
+ lcdc_dev->driver.frame_time.framedone_t;
lcdc_dev->driver.frame_time.framedone_t = cpu_clock(0);
lcdc_msk_reg(lcdc_dev, INTR_CLEAR, m_LINE_FLAG0_INTR_CLR,
v_LINE_FLAG0_INTR_CLR(1));
+
+ if (cabc_status == 1) {
+ cabc_gamma_base =
+ lcdc_dev->driver.cur_screen->cabc_gamma_base;
+ scale_global_limit = lcdc_readl(lcdc_dev, CABC_DEBUG2);
+ scale_global_limit_reg = scale_global_limit;
+ scale_global_limit >>= 16;
+ scale_global_limit &= 0xff;
+
+ if (lcdc_dev->driver.cabc_pwm_pol == 1) {/*negative*/
+ pwm_plus = pwm_period_hpr - pwm_duty_lpr;
+ cabc_pwm_lut_value =
+ pwm_period_hpr -
+ ((cabc_gamma_base[scale_global_limit] * pwm_plus) >> 16);
+ } else {/*positive*/
+ pwm_plus = pwm_duty_lpr;
+ cabc_pwm_lut_value =
+ cabc_gamma_base[scale_global_limit] *
+ pwm_plus >> 16;
+ }
+ rk_pwm_set(pwm_period_hpr, cabc_pwm_lut_value);
+ }
} else if (intr_status & m_LINE_FLAG1_INTR_STS) {
/*line flag1 */
lcdc_msk_reg(lcdc_dev, INTR_CLEAR, m_LINE_FLAG1_INTR_CLR,
dev_err(&pdev->dev, "can't find lcdc pmu grf property\n");
return PTR_ERR(lcdc_dev->pmugrf_base);
}
+
lcdc_dev->id = 0;
dev_set_name(lcdc_dev->dev, "lcdc%d", lcdc_dev->id);
dev_drv = &lcdc_dev->driver;