diff options
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 95 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss.h | 5 | ||||
-rw-r--r-- | drivers/video/omap2/dss/manager.c | 123 | ||||
-rw-r--r-- | drivers/video/omap2/dss/overlay.c | 4 | ||||
-rw-r--r-- | include/video/omapdss.h | 17 |
5 files changed, 192 insertions, 52 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 9681717..d2b1912 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -739,62 +739,22 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, } } -static void _dispc_setup_color_conv_coef(void) +void _dispc_setup_color_conv_coef(enum omap_plane plane, + const struct omap_dss_cconv_coefs *ct) { - const struct color_conv_coef { - int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; - int full_range; - } ctbl_bt601_5 = { - 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, - }; - - const struct color_conv_coef *ct; + BUG_ON(plane < OMAP_DSS_VIDEO1 || plane > OMAP_DSS_VIDEO3); #define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) - ct = &ctbl_bt601_5; - - dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0), - CVAL(ct->rcr, ct->ry)); - dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1), - CVAL(ct->gy, ct->rcb)); - dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2), - CVAL(ct->gcb, ct->gcr)); - dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3), - CVAL(ct->bcr, ct->by)); - dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4), - CVAL(0, ct->bcb)); - - dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0), - CVAL(ct->rcr, ct->ry)); - dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1), - CVAL(ct->gy, ct->rcb)); - dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2), - CVAL(ct->gcb, ct->gcr)); - dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3), - CVAL(ct->bcr, ct->by)); - dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4), - CVAL(0, ct->bcb)); - - dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO3, 0), - CVAL(ct->rcr, ct->ry)); - dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO3, 1), - CVAL(ct->gy, ct->rcb)); - dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO3, 2), - CVAL(ct->gcb, ct->gcr)); - dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO3, 3), - CVAL(ct->bcr, ct->by)); - dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO3, 4), - CVAL(0, ct->bcb)); + dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->rcr, ct->ry)); + dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->gy, ct->rcb)); + dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->gcb, ct->gcr)); + dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->bcr, ct->by)); + dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->bcb)); #undef CVAL - REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1), - ct->full_range, 11, 11); - REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2), - ct->full_range, 11, 11); - REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO3), - ct->full_range, 11, 11); + REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11); } @@ -1080,6 +1040,40 @@ void dispc_enable_zorder(enum omap_plane plane, bool enable) dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); } +void dispc_enable_cpr(enum omap_channel channel, bool enable) +{ + u16 reg; + + if (channel == OMAP_DSS_CHANNEL_LCD) + reg = DISPC_CONFIG; + else if (channel == OMAP_DSS_CHANNEL_LCD2) + reg = DISPC_CONFIG2; + else + return; + + REG_FLD_MOD(reg, enable, 15, 15); +} + +void dispc_set_cpr_coef(enum omap_channel channel, + struct omap_dss_cpr_coefs *coefs) +{ + u32 coef_r, coef_g, coef_b; + + if (channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2) + return; + + coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) | + FLD_VAL(coefs->rb, 9, 0); + coef_g = FLD_VAL(coefs->gr, 31, 22) | FLD_VAL(coefs->gg, 20, 11) | + FLD_VAL(coefs->gb, 9, 0); + coef_b = FLD_VAL(coefs->br, 31, 22) | FLD_VAL(coefs->bg, 20, 11) | + FLD_VAL(coefs->bb, 9, 0); + + dispc_write_reg(DISPC_CPR_COEF_R(channel), coef_r); + dispc_write_reg(DISPC_CPR_COEF_G(channel), coef_g); + dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b); +} + static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) { u32 val; @@ -2206,7 +2200,6 @@ int dispc_setup_plane(enum omap_plane plane, _dispc_set_pre_mult_alpha(plane, pre_mult_alpha); _dispc_setup_global_alpha(plane, global_alpha); - return 0; } @@ -3736,8 +3729,6 @@ static void _omap_dispc_initial_config(void) if (cpu_is_omap24xx()) __raw_writel(0x402000b0, OMAP2_L3_IO_ADDRESS(0x680050a0)); - _dispc_setup_color_conv_coef(); - dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY); dispc_read_plane_fifo_sizes(); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 6d59b26..bed345e 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -401,6 +401,11 @@ void dispc_set_burst_size(enum omap_plane plane, void dispc_set_zorder(enum omap_plane plane, enum omap_overlay_zorder zorder); void dispc_enable_zorder(enum omap_plane plane, bool enable); +void dispc_enable_cpr(enum omap_channel channel, bool enable); +void dispc_set_cpr_coef(enum omap_channel channel, + struct omap_dss_cpr_coefs *coefs); +void _dispc_setup_color_conv_coef(enum omap_plane plane, + const struct omap_dss_cconv_coefs *ct); void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr); void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr); diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 106767d..3e5654a 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -279,6 +279,108 @@ static ssize_t manager_alpha_blending_enabled_store( return size; } +static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.cpr_enable); +} + +static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr, + const char *buf, size_t size) +{ + struct omap_overlay_manager_info info; + int v; + int r; + bool enable; + + if (!dss_has_feature(FEAT_CPR)) + return -ENODEV; + + r = kstrtoint(buf, 0, &v); + if (r) + return r; + + enable = !!v; + + mgr->get_manager_info(mgr, &info); + + if (info.cpr_enable == enable) + return size; + + info.cpr_enable = enable; + + r = mgr->set_manager_info(mgr, &info); + if (r) + return r; + + r = mgr->apply(mgr); + if (r) + return r; + + return size; +} + +static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr, + char *buf) +{ + struct omap_overlay_manager_info info; + + mgr->get_manager_info(mgr, &info); + + return snprintf(buf, PAGE_SIZE, + "%d %d %d %d %d %d %d %d %d\n", + info.cpr_coefs.rr, + info.cpr_coefs.rg, + info.cpr_coefs.rb, + info.cpr_coefs.gr, + info.cpr_coefs.gg, + info.cpr_coefs.gb, + info.cpr_coefs.br, + info.cpr_coefs.bg, + info.cpr_coefs.bb); +} + +static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr, + const char *buf, size_t size) +{ + struct omap_overlay_manager_info info; + struct omap_dss_cpr_coefs coefs; + int r, i; + s16 *arr; + + if (!dss_has_feature(FEAT_CPR)) + return -ENODEV; + + if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd", + &coefs.rr, &coefs.rg, &coefs.rb, + &coefs.gr, &coefs.gg, &coefs.gb, + &coefs.br, &coefs.bg, &coefs.bb) != 9) + return -EINVAL; + + arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb, + coefs.gr, coefs.gg, coefs.gb, + coefs.br, coefs.bg, coefs.bb }; + + for (i = 0; i < 9; ++i) { + if (arr[i] < -512 || arr[i] > 511) + return -EINVAL; + } + + mgr->get_manager_info(mgr, &info); + + info.cpr_coefs = coefs; + + r = mgr->set_manager_info(mgr, &info); + if (r) + return r; + + r = mgr->apply(mgr); + if (r) + return r; + + return size; +} + struct manager_attribute { struct attribute attr; ssize_t (*show)(struct omap_overlay_manager *, char *); @@ -304,6 +406,12 @@ static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR, static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR, manager_alpha_blending_enabled_show, manager_alpha_blending_enabled_store); +static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR, + manager_cpr_enable_show, + manager_cpr_enable_store); +static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR, + manager_cpr_coef_show, + manager_cpr_coef_store); static struct attribute *manager_sysfs_attrs[] = { @@ -314,6 +422,8 @@ static struct attribute *manager_sysfs_attrs[] = { &manager_attr_trans_key_value.attr, &manager_attr_trans_key_enabled.attr, &manager_attr_alpha_blending_enabled.attr, + &manager_attr_cpr_enable.attr, + &manager_attr_cpr_coef.attr, NULL }; @@ -441,6 +551,7 @@ struct overlay_cache_data { bool manual_update; enum omap_overlay_zorder zorder; + struct omap_dss_cconv_coefs cconv; }; struct manager_cache_data { @@ -472,6 +583,9 @@ struct manager_cache_data { bool enlarge_update_area; struct callback_states cb; /* callback data for the last 3 states */ + + bool cpr_enable; + struct omap_dss_cpr_coefs cpr_coefs; }; static struct { @@ -956,6 +1070,8 @@ static int configure_overlay(enum omap_plane plane) dispc_set_zorder(plane, c->zorder); dispc_enable_zorder(plane, 1); dispc_setup_plane_fifo(plane, c->fifo_low, c->fifo_high); + if (plane != OMAP_DSS_GFX) + _dispc_setup_color_conv_coef(plane, &c->cconv); dispc_enable_plane(plane, 1); @@ -982,6 +1098,10 @@ static void configure_manager(enum omap_channel channel) } else { dispc_enable_alpha_blending(channel, c->alpha_enabled); } + if (dss_has_feature(FEAT_CPR)) { + dispc_enable_cpr(channel, c->cpr_enable); + dispc_set_cpr_coef(channel, &c->cpr_coefs); + } } /* configure_dispc() tries to write values from cache to shadow registers. @@ -1515,6 +1635,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) oc->max_x_decim = ovl->info.max_x_decim; oc->min_y_decim = ovl->info.min_y_decim; oc->max_y_decim = ovl->info.max_y_decim; + oc->cconv = ovl->info.cconv; oc->replication = dss_use_replication(dssdev, ovl->info.color_mode); @@ -1574,6 +1695,8 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) mc->trans_key = mgr->info.trans_key; mc->trans_enabled = mgr->info.trans_enabled; mc->alpha_enabled = mgr->info.alpha_enabled; + mc->cpr_coefs = mgr->info.cpr_coefs; + mc->cpr_enable = mgr->info.cpr_enable; mc->manual_upd_display = dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 2a5ce97..6c6ba8b 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -738,6 +738,9 @@ void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr) void dss_init_overlays(struct platform_device *pdev) { int i, r; + const struct omap_dss_cconv_coefs ctbl_bt601_5 = { + 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, + }; INIT_LIST_HEAD(&overlay_list); @@ -793,6 +796,7 @@ void dss_init_overlays(struct platform_device *pdev) ovl->info.min_x_decim = ovl->info.min_y_decim = 1; ovl->info.max_x_decim = ovl->info.max_y_decim = cpu_is_omap44xx() ? 16 : 1; + ovl->info.cconv = ctbl_bt601_5; ovl->set_manager = &omap_dss_set_manager; ovl->unset_manager = &omap_dss_unset_manager; diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 565a49b..fc626d2 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -337,6 +337,19 @@ struct omapdss_ovl_cb { void *data; }; +struct omap_dss_cpr_coefs { + s16 rr, rg, rb; + s16 gr, gg, gb; + s16 br, bg, bb; +}; + +struct omap_dss_cconv_coefs { + s16 ry, rcr, rcb; + s16 gy, gcr, gcb; + s16 by, bcr, bcb; + u16 full_range; +} __attribute__ ((aligned(4))); + struct omap_overlay_info { bool enabled; @@ -359,6 +372,7 @@ struct omap_overlay_info { u8 pre_mult_alpha; enum omap_overlay_zorder zorder; u16 min_x_decim, max_x_decim, min_y_decim, max_y_decim; + struct omap_dss_cconv_coefs cconv; struct omapdss_ovl_cb cb; }; @@ -402,6 +416,9 @@ struct omap_overlay_manager_info { bool alpha_enabled; struct omapdss_ovl_cb cb; + + bool cpr_enable; + struct omap_dss_cpr_coefs cpr_coefs; }; struct omap_overlay_manager { |