Loading drivers/video/fbdev/omap2/dss/dispc.c +99 −15 Original line number Diff line number Diff line Loading @@ -96,6 +96,9 @@ struct dispc_features { bool mstandby_workaround:1; bool set_max_preload:1; /* PIXEL_INC is not added to the last pixel of a line */ bool last_pixel_inc_missing:1; }; #define DISPC_MAX_NR_FIFOS 5 Loading Loading @@ -1742,6 +1745,15 @@ static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation, row_repeat = false; } /* * OMAP4/5 Errata i631: * NV12 in 1D mode must use ROTATION=1. Otherwise DSS will fetch extra * rows beyond the framebuffer, which may cause OCP error. */ if (color_mode == OMAP_DSS_COLOR_NV12 && rotation_type != OMAP_DSS_ROT_TILER) vidrot = 1; REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12); if (dss_has_feature(FEAT_ROWREPEATENABLE)) REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), Loading Loading @@ -2155,7 +2167,7 @@ static unsigned long calc_core_clk_five_taps(unsigned long pclk, if (height > out_height) { unsigned int ppl = mgr_timings->x_res; tmp = pclk * height * out_width; tmp = (u64)pclk * height * out_width; do_div(tmp, 2 * out_height * ppl); core_clk = tmp; Loading @@ -2163,14 +2175,14 @@ static unsigned long calc_core_clk_five_taps(unsigned long pclk, if (ppl == out_width) return 0; tmp = pclk * (height - 2 * out_height) * out_width; tmp = (u64)pclk * (height - 2 * out_height) * out_width; do_div(tmp, 2 * out_height * (ppl - out_width)); core_clk = max_t(u32, core_clk, tmp); } } if (width > out_width) { tmp = pclk * width; tmp = (u64)pclk * width; do_div(tmp, out_width); core_clk = max_t(u32, core_clk, tmp); Loading Loading @@ -2268,6 +2280,11 @@ static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk, } } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); if (error) { DSSERR("failed to find scaling settings\n"); return -EINVAL; } if (in_width > maxsinglelinewidth) { DSSERR("Cannot scale max input width exceeded"); return -EINVAL; Loading @@ -2284,7 +2301,6 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk, { int error; u16 in_width, in_height; int min_factor = min(*decim_x, *decim_y); const int maxsinglelinewidth = dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); Loading Loading @@ -2318,20 +2334,32 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk, error = (error || in_width > maxsinglelinewidth * 2 || (in_width > maxsinglelinewidth && *five_taps) || !*core_clk || *core_clk > dispc_core_clk_rate()); if (error) { if (*decim_x == *decim_y) { *decim_x = min_factor; ++*decim_y; if (!error) { /* verify that we're inside the limits of scaler */ if (in_width / 4 > out_width) error = 1; if (*five_taps) { if (in_height / 4 > out_height) error = 1; } else { swap(*decim_x, *decim_y); if (*decim_x < *decim_y) ++*decim_x; if (in_height / 2 > out_height) error = 1; } } if (error) ++*decim_y; } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width, height, out_width, out_height, *five_taps)) { if (error) { DSSERR("failed to find scaling settings\n"); return -EINVAL; } if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, in_width, in_height, out_width, out_height, *five_taps)) { DSSERR("horizontal timing too tight\n"); return -EINVAL; } Loading Loading @@ -2391,6 +2419,9 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk, return 0; } #define DIV_FRAC(dividend, divisor) \ ((dividend) * 100 / (divisor) - ((dividend) / (divisor) * 100)) static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, enum omap_overlay_caps caps, const struct omap_video_timings *mgr_timings, Loading Loading @@ -2450,8 +2481,19 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, if (ret) return ret; DSSDBG("required core clk rate = %lu Hz\n", core_clk); DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate()); DSSDBG("%dx%d -> %dx%d (%d.%02d x %d.%02d), decim %dx%d %dx%d (%d.%02d x %d.%02d), taps %d, req clk %lu, cur clk %lu\n", width, height, out_width, out_height, out_width / width, DIV_FRAC(out_width, width), out_height / height, DIV_FRAC(out_height, height), decim_x, decim_y, width / decim_x, height / decim_y, out_width / (width / decim_x), DIV_FRAC(out_width, width / decim_x), out_height / (height / decim_y), DIV_FRAC(out_height, height / decim_y), *five_taps ? 5 : 3, core_clk, dispc_core_clk_rate()); if (!core_clk || core_clk > dispc_core_clk_rate()) { DSSERR("failed to set up scaling, " Loading Loading @@ -2534,6 +2576,21 @@ static int dispc_ovl_setup_common(enum omap_plane plane, if (paddr == 0 && rotation_type != OMAP_DSS_ROT_TILER) return -EINVAL; switch (color_mode) { case OMAP_DSS_COLOR_YUV2: case OMAP_DSS_COLOR_UYVY: case OMAP_DSS_COLOR_NV12: if (in_width & 1) { DSSERR("input width %d is not even for YUV format\n", in_width); return -EINVAL; } break; default: break; } out_width = out_width == 0 ? width : out_width; out_height = out_height == 0 ? height : out_height; Loading Loading @@ -2564,6 +2621,27 @@ static int dispc_ovl_setup_common(enum omap_plane plane, in_width = in_width / x_predecim; in_height = in_height / y_predecim; if (x_predecim > 1 || y_predecim > 1) DSSDBG("predecimation %d x %x, new input size %d x %d\n", x_predecim, y_predecim, in_width, in_height); switch (color_mode) { case OMAP_DSS_COLOR_YUV2: case OMAP_DSS_COLOR_UYVY: case OMAP_DSS_COLOR_NV12: if (in_width & 1) { DSSDBG("predecimated input width is not even for YUV format\n"); DSSDBG("adjusting input width %d -> %d\n", in_width, in_width & ~1); in_width &= ~1; } break; default: break; } if (color_mode == OMAP_DSS_COLOR_YUV2 || color_mode == OMAP_DSS_COLOR_UYVY || color_mode == OMAP_DSS_COLOR_NV12) Loading Loading @@ -2633,6 +2711,9 @@ static int dispc_ovl_setup_common(enum omap_plane plane, dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1); } if (dispc.feat->last_pixel_inc_missing) row_inc += pix_inc - 1; dispc_ovl_set_row_inc(plane, row_inc); dispc_ovl_set_pix_inc(plane, pix_inc); Loading Loading @@ -3710,6 +3791,7 @@ static const struct dispc_features omap24xx_dispc_feats = { .num_fifos = 3, .no_framedone_tv = true, .set_max_preload = false, .last_pixel_inc_missing = true, }; static const struct dispc_features omap34xx_rev1_0_dispc_feats = { Loading @@ -3730,6 +3812,7 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats = { .num_fifos = 3, .no_framedone_tv = true, .set_max_preload = false, .last_pixel_inc_missing = true, }; static const struct dispc_features omap34xx_rev3_0_dispc_feats = { Loading @@ -3750,6 +3833,7 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats = { .num_fifos = 3, .no_framedone_tv = true, .set_max_preload = false, .last_pixel_inc_missing = true, }; static const struct dispc_features omap44xx_dispc_feats = { Loading drivers/video/fbdev/omap2/dss/hdmi4.c +1 −1 Original line number Diff line number Diff line Loading @@ -230,9 +230,9 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) err_mgr_enable: hdmi_wp_video_stop(&hdmi.wp); err_vid_enable: err_phy_cfg: hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); err_phy_pwr: err_phy_cfg: err_pll_cfg: dss_pll_disable(&hdmi.pll.pll); err_pll_enable: Loading drivers/video/fbdev/omap2/dss/hdmi_wp.c +16 −0 Original line number Diff line number Diff line Loading @@ -110,7 +110,23 @@ int hdmi_wp_video_start(struct hdmi_wp_data *wp) void hdmi_wp_video_stop(struct hdmi_wp_data *wp) { int i; hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_FRAME_DONE); REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, false, 31, 31); for (i = 0; i < 50; ++i) { u32 v; msleep(20); v = hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS_RAW); if (v & HDMI_IRQ_VIDEO_FRAME_DONE) return; } DSSERR("no HDMI FRAMEDONE when disabling output\n"); } void hdmi_wp_video_config_format(struct hdmi_wp_data *wp, Loading Loading
drivers/video/fbdev/omap2/dss/dispc.c +99 −15 Original line number Diff line number Diff line Loading @@ -96,6 +96,9 @@ struct dispc_features { bool mstandby_workaround:1; bool set_max_preload:1; /* PIXEL_INC is not added to the last pixel of a line */ bool last_pixel_inc_missing:1; }; #define DISPC_MAX_NR_FIFOS 5 Loading Loading @@ -1742,6 +1745,15 @@ static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation, row_repeat = false; } /* * OMAP4/5 Errata i631: * NV12 in 1D mode must use ROTATION=1. Otherwise DSS will fetch extra * rows beyond the framebuffer, which may cause OCP error. */ if (color_mode == OMAP_DSS_COLOR_NV12 && rotation_type != OMAP_DSS_ROT_TILER) vidrot = 1; REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12); if (dss_has_feature(FEAT_ROWREPEATENABLE)) REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), Loading Loading @@ -2155,7 +2167,7 @@ static unsigned long calc_core_clk_five_taps(unsigned long pclk, if (height > out_height) { unsigned int ppl = mgr_timings->x_res; tmp = pclk * height * out_width; tmp = (u64)pclk * height * out_width; do_div(tmp, 2 * out_height * ppl); core_clk = tmp; Loading @@ -2163,14 +2175,14 @@ static unsigned long calc_core_clk_five_taps(unsigned long pclk, if (ppl == out_width) return 0; tmp = pclk * (height - 2 * out_height) * out_width; tmp = (u64)pclk * (height - 2 * out_height) * out_width; do_div(tmp, 2 * out_height * (ppl - out_width)); core_clk = max_t(u32, core_clk, tmp); } } if (width > out_width) { tmp = pclk * width; tmp = (u64)pclk * width; do_div(tmp, out_width); core_clk = max_t(u32, core_clk, tmp); Loading Loading @@ -2268,6 +2280,11 @@ static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk, } } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); if (error) { DSSERR("failed to find scaling settings\n"); return -EINVAL; } if (in_width > maxsinglelinewidth) { DSSERR("Cannot scale max input width exceeded"); return -EINVAL; Loading @@ -2284,7 +2301,6 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk, { int error; u16 in_width, in_height; int min_factor = min(*decim_x, *decim_y); const int maxsinglelinewidth = dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); Loading Loading @@ -2318,20 +2334,32 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk, error = (error || in_width > maxsinglelinewidth * 2 || (in_width > maxsinglelinewidth && *five_taps) || !*core_clk || *core_clk > dispc_core_clk_rate()); if (error) { if (*decim_x == *decim_y) { *decim_x = min_factor; ++*decim_y; if (!error) { /* verify that we're inside the limits of scaler */ if (in_width / 4 > out_width) error = 1; if (*five_taps) { if (in_height / 4 > out_height) error = 1; } else { swap(*decim_x, *decim_y); if (*decim_x < *decim_y) ++*decim_x; if (in_height / 2 > out_height) error = 1; } } if (error) ++*decim_y; } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width, height, out_width, out_height, *five_taps)) { if (error) { DSSERR("failed to find scaling settings\n"); return -EINVAL; } if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, in_width, in_height, out_width, out_height, *five_taps)) { DSSERR("horizontal timing too tight\n"); return -EINVAL; } Loading Loading @@ -2391,6 +2419,9 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk, return 0; } #define DIV_FRAC(dividend, divisor) \ ((dividend) * 100 / (divisor) - ((dividend) / (divisor) * 100)) static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, enum omap_overlay_caps caps, const struct omap_video_timings *mgr_timings, Loading Loading @@ -2450,8 +2481,19 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, if (ret) return ret; DSSDBG("required core clk rate = %lu Hz\n", core_clk); DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate()); DSSDBG("%dx%d -> %dx%d (%d.%02d x %d.%02d), decim %dx%d %dx%d (%d.%02d x %d.%02d), taps %d, req clk %lu, cur clk %lu\n", width, height, out_width, out_height, out_width / width, DIV_FRAC(out_width, width), out_height / height, DIV_FRAC(out_height, height), decim_x, decim_y, width / decim_x, height / decim_y, out_width / (width / decim_x), DIV_FRAC(out_width, width / decim_x), out_height / (height / decim_y), DIV_FRAC(out_height, height / decim_y), *five_taps ? 5 : 3, core_clk, dispc_core_clk_rate()); if (!core_clk || core_clk > dispc_core_clk_rate()) { DSSERR("failed to set up scaling, " Loading Loading @@ -2534,6 +2576,21 @@ static int dispc_ovl_setup_common(enum omap_plane plane, if (paddr == 0 && rotation_type != OMAP_DSS_ROT_TILER) return -EINVAL; switch (color_mode) { case OMAP_DSS_COLOR_YUV2: case OMAP_DSS_COLOR_UYVY: case OMAP_DSS_COLOR_NV12: if (in_width & 1) { DSSERR("input width %d is not even for YUV format\n", in_width); return -EINVAL; } break; default: break; } out_width = out_width == 0 ? width : out_width; out_height = out_height == 0 ? height : out_height; Loading Loading @@ -2564,6 +2621,27 @@ static int dispc_ovl_setup_common(enum omap_plane plane, in_width = in_width / x_predecim; in_height = in_height / y_predecim; if (x_predecim > 1 || y_predecim > 1) DSSDBG("predecimation %d x %x, new input size %d x %d\n", x_predecim, y_predecim, in_width, in_height); switch (color_mode) { case OMAP_DSS_COLOR_YUV2: case OMAP_DSS_COLOR_UYVY: case OMAP_DSS_COLOR_NV12: if (in_width & 1) { DSSDBG("predecimated input width is not even for YUV format\n"); DSSDBG("adjusting input width %d -> %d\n", in_width, in_width & ~1); in_width &= ~1; } break; default: break; } if (color_mode == OMAP_DSS_COLOR_YUV2 || color_mode == OMAP_DSS_COLOR_UYVY || color_mode == OMAP_DSS_COLOR_NV12) Loading Loading @@ -2633,6 +2711,9 @@ static int dispc_ovl_setup_common(enum omap_plane plane, dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1); } if (dispc.feat->last_pixel_inc_missing) row_inc += pix_inc - 1; dispc_ovl_set_row_inc(plane, row_inc); dispc_ovl_set_pix_inc(plane, pix_inc); Loading Loading @@ -3710,6 +3791,7 @@ static const struct dispc_features omap24xx_dispc_feats = { .num_fifos = 3, .no_framedone_tv = true, .set_max_preload = false, .last_pixel_inc_missing = true, }; static const struct dispc_features omap34xx_rev1_0_dispc_feats = { Loading @@ -3730,6 +3812,7 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats = { .num_fifos = 3, .no_framedone_tv = true, .set_max_preload = false, .last_pixel_inc_missing = true, }; static const struct dispc_features omap34xx_rev3_0_dispc_feats = { Loading @@ -3750,6 +3833,7 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats = { .num_fifos = 3, .no_framedone_tv = true, .set_max_preload = false, .last_pixel_inc_missing = true, }; static const struct dispc_features omap44xx_dispc_feats = { Loading
drivers/video/fbdev/omap2/dss/hdmi4.c +1 −1 Original line number Diff line number Diff line Loading @@ -230,9 +230,9 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) err_mgr_enable: hdmi_wp_video_stop(&hdmi.wp); err_vid_enable: err_phy_cfg: hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); err_phy_pwr: err_phy_cfg: err_pll_cfg: dss_pll_disable(&hdmi.pll.pll); err_pll_enable: Loading
drivers/video/fbdev/omap2/dss/hdmi_wp.c +16 −0 Original line number Diff line number Diff line Loading @@ -110,7 +110,23 @@ int hdmi_wp_video_start(struct hdmi_wp_data *wp) void hdmi_wp_video_stop(struct hdmi_wp_data *wp) { int i; hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_FRAME_DONE); REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, false, 31, 31); for (i = 0; i < 50; ++i) { u32 v; msleep(20); v = hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS_RAW); if (v & HDMI_IRQ_VIDEO_FRAME_DONE) return; } DSSERR("no HDMI FRAMEDONE when disabling output\n"); } void hdmi_wp_video_config_format(struct hdmi_wp_data *wp, Loading