aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap2/dss/dispc.c110
1 files changed, 64 insertions, 46 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 9c23ce8aed49..d65568929ac8 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -86,13 +86,13 @@ struct dispc_features {
86 u16 sw_max; 86 u16 sw_max;
87 u16 vp_max; 87 u16 vp_max;
88 u16 hp_max; 88 u16 hp_max;
89 int (*calc_scaling) (enum omap_channel channel, 89 int (*calc_scaling) (enum omap_plane plane,
90 const struct omap_video_timings *mgr_timings, 90 const struct omap_video_timings *mgr_timings,
91 u16 width, u16 height, u16 out_width, u16 out_height, 91 u16 width, u16 height, u16 out_width, u16 out_height,
92 enum omap_color_mode color_mode, bool *five_taps, 92 enum omap_color_mode color_mode, bool *five_taps,
93 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, 93 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
94 u16 pos_x, unsigned long *core_clk); 94 u16 pos_x, unsigned long *core_clk);
95 unsigned long (*calc_core_clk) (enum omap_channel channel, 95 unsigned long (*calc_core_clk) (enum omap_plane plane,
96 u16 width, u16 height, u16 out_width, u16 out_height); 96 u16 width, u16 height, u16 out_width, u16 out_height);
97 u8 num_fifos; 97 u8 num_fifos;
98 98
@@ -236,6 +236,8 @@ static const struct {
236}; 236};
237 237
238static void _omap_dispc_set_irqs(void); 238static void _omap_dispc_set_irqs(void);
239static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
240static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
239 241
240static inline void dispc_write_reg(const u16 idx, u32 val) 242static inline void dispc_write_reg(const u16 idx, u32 val)
241{ 243{
@@ -1919,22 +1921,19 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
1919 * This function is used to avoid synclosts in OMAP3, because of some 1921 * This function is used to avoid synclosts in OMAP3, because of some
1920 * undocumented horizontal position and timing related limitations. 1922 * undocumented horizontal position and timing related limitations.
1921 */ 1923 */
1922static int check_horiz_timing_omap3(enum omap_channel channel, 1924static int check_horiz_timing_omap3(enum omap_plane plane,
1923 const struct omap_video_timings *t, u16 pos_x, 1925 const struct omap_video_timings *t, u16 pos_x,
1924 u16 width, u16 height, u16 out_width, u16 out_height) 1926 u16 width, u16 height, u16 out_width, u16 out_height)
1925{ 1927{
1926 int DS = DIV_ROUND_UP(height, out_height); 1928 int DS = DIV_ROUND_UP(height, out_height);
1927 unsigned long nonactive, lclk, pclk; 1929 unsigned long nonactive;
1928 static const u8 limits[3] = { 8, 10, 20 }; 1930 static const u8 limits[3] = { 8, 10, 20 };
1929 u64 val, blank; 1931 u64 val, blank;
1932 unsigned long pclk = dispc_plane_pclk_rate(plane);
1933 unsigned long lclk = dispc_plane_lclk_rate(plane);
1930 int i; 1934 int i;
1931 1935
1932 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width; 1936 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
1933 pclk = dispc_mgr_pclk_rate(channel);
1934 if (dss_mgr_is_lcd(channel))
1935 lclk = dispc_mgr_lclk_rate(channel);
1936 else
1937 lclk = dispc_fclk_rate();
1938 1937
1939 i = 0; 1938 i = 0;
1940 if (out_height < height) 1939 if (out_height < height)
@@ -1971,13 +1970,14 @@ static int check_horiz_timing_omap3(enum omap_channel channel,
1971 return 0; 1970 return 0;
1972} 1971}
1973 1972
1974static unsigned long calc_core_clk_five_taps(enum omap_channel channel, 1973static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
1975 const struct omap_video_timings *mgr_timings, u16 width, 1974 const struct omap_video_timings *mgr_timings, u16 width,
1976 u16 height, u16 out_width, u16 out_height, 1975 u16 height, u16 out_width, u16 out_height,
1977 enum omap_color_mode color_mode) 1976 enum omap_color_mode color_mode)
1978{ 1977{
1979 u32 core_clk = 0; 1978 u32 core_clk = 0;
1980 u64 tmp, pclk = dispc_mgr_pclk_rate(channel); 1979 u64 tmp;
1980 unsigned long pclk = dispc_plane_pclk_rate(plane);
1981 1981
1982 if (height <= out_height && width <= out_width) 1982 if (height <= out_height && width <= out_width)
1983 return (unsigned long) pclk; 1983 return (unsigned long) pclk;
@@ -2011,10 +2011,10 @@ static unsigned long calc_core_clk_five_taps(enum omap_channel channel,
2011 return core_clk; 2011 return core_clk;
2012} 2012}
2013 2013
2014static unsigned long calc_core_clk_24xx(enum omap_channel channel, u16 width, 2014static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width,
2015 u16 height, u16 out_width, u16 out_height) 2015 u16 height, u16 out_width, u16 out_height)
2016{ 2016{
2017 unsigned long pclk = dispc_mgr_pclk_rate(channel); 2017 unsigned long pclk = dispc_plane_pclk_rate(plane);
2018 2018
2019 if (height > out_height && width > out_width) 2019 if (height > out_height && width > out_width)
2020 return pclk * 4; 2020 return pclk * 4;
@@ -2022,11 +2022,11 @@ static unsigned long calc_core_clk_24xx(enum omap_channel channel, u16 width,
2022 return pclk * 2; 2022 return pclk * 2;
2023} 2023}
2024 2024
2025static unsigned long calc_core_clk_34xx(enum omap_channel channel, u16 width, 2025static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
2026 u16 height, u16 out_width, u16 out_height) 2026 u16 height, u16 out_width, u16 out_height)
2027{ 2027{
2028 unsigned int hf, vf; 2028 unsigned int hf, vf;
2029 unsigned long pclk = dispc_mgr_pclk_rate(channel); 2029 unsigned long pclk = dispc_plane_pclk_rate(plane);
2030 2030
2031 /* 2031 /*
2032 * FIXME how to determine the 'A' factor 2032 * FIXME how to determine the 'A' factor
@@ -2049,10 +2049,10 @@ static unsigned long calc_core_clk_34xx(enum omap_channel channel, u16 width,
2049 return pclk * vf * hf; 2049 return pclk * vf * hf;
2050} 2050}
2051 2051
2052static unsigned long calc_core_clk_44xx(enum omap_channel channel, u16 width, 2052static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
2053 u16 height, u16 out_width, u16 out_height) 2053 u16 height, u16 out_width, u16 out_height)
2054{ 2054{
2055 unsigned long pclk = dispc_mgr_pclk_rate(channel); 2055 unsigned long pclk = dispc_plane_pclk_rate(plane);
2056 2056
2057 if (width > out_width) 2057 if (width > out_width)
2058 return DIV_ROUND_UP(pclk, out_width) * width; 2058 return DIV_ROUND_UP(pclk, out_width) * width;
@@ -2060,7 +2060,7 @@ static unsigned long calc_core_clk_44xx(enum omap_channel channel, u16 width,
2060 return pclk; 2060 return pclk;
2061} 2061}
2062 2062
2063static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel, 2063static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
2064 const struct omap_video_timings *mgr_timings, 2064 const struct omap_video_timings *mgr_timings,
2065 u16 width, u16 height, u16 out_width, u16 out_height, 2065 u16 width, u16 height, u16 out_width, u16 out_height,
2066 enum omap_color_mode color_mode, bool *five_taps, 2066 enum omap_color_mode color_mode, bool *five_taps,
@@ -2072,12 +2072,13 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel,
2072 int min_factor = min(*decim_x, *decim_y); 2072 int min_factor = min(*decim_x, *decim_y);
2073 const int maxsinglelinewidth = 2073 const int maxsinglelinewidth =
2074 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); 2074 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2075
2075 *five_taps = false; 2076 *five_taps = false;
2076 2077
2077 do { 2078 do {
2078 in_height = DIV_ROUND_UP(height, *decim_y); 2079 in_height = DIV_ROUND_UP(height, *decim_y);
2079 in_width = DIV_ROUND_UP(width, *decim_x); 2080 in_width = DIV_ROUND_UP(width, *decim_x);
2080 *core_clk = dispc.feat->calc_core_clk(channel, in_width, 2081 *core_clk = dispc.feat->calc_core_clk(plane, in_width,
2081 in_height, out_width, out_height); 2082 in_height, out_width, out_height);
2082 error = (in_width > maxsinglelinewidth || !*core_clk || 2083 error = (in_width > maxsinglelinewidth || !*core_clk ||
2083 *core_clk > dispc_core_clk_rate()); 2084 *core_clk > dispc_core_clk_rate());
@@ -2100,7 +2101,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel,
2100 return 0; 2101 return 0;
2101} 2102}
2102 2103
2103static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel, 2104static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
2104 const struct omap_video_timings *mgr_timings, 2105 const struct omap_video_timings *mgr_timings,
2105 u16 width, u16 height, u16 out_width, u16 out_height, 2106 u16 width, u16 height, u16 out_width, u16 out_height,
2106 enum omap_color_mode color_mode, bool *five_taps, 2107 enum omap_color_mode color_mode, bool *five_taps,
@@ -2116,18 +2117,19 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel,
2116 do { 2117 do {
2117 in_height = DIV_ROUND_UP(height, *decim_y); 2118 in_height = DIV_ROUND_UP(height, *decim_y);
2118 in_width = DIV_ROUND_UP(width, *decim_x); 2119 in_width = DIV_ROUND_UP(width, *decim_x);
2119 *core_clk = calc_core_clk_five_taps(channel, mgr_timings, 2120 *core_clk = calc_core_clk_five_taps(plane, mgr_timings,
2120 in_width, in_height, out_width, out_height, color_mode); 2121 in_width, in_height, out_width, out_height, color_mode);
2121 2122
2122 error = check_horiz_timing_omap3(channel, mgr_timings, pos_x, 2123 error = check_horiz_timing_omap3(plane, mgr_timings,
2123 in_width, in_height, out_width, out_height); 2124 pos_x, in_width, in_height, out_width,
2125 out_height);
2124 2126
2125 if (in_width > maxsinglelinewidth) 2127 if (in_width > maxsinglelinewidth)
2126 if (in_height > out_height && 2128 if (in_height > out_height &&
2127 in_height < out_height * 2) 2129 in_height < out_height * 2)
2128 *five_taps = false; 2130 *five_taps = false;
2129 if (!*five_taps) 2131 if (!*five_taps)
2130 *core_clk = dispc.feat->calc_core_clk(channel, in_width, 2132 *core_clk = dispc.feat->calc_core_clk(plane, in_width,
2131 in_height, out_width, out_height); 2133 in_height, out_width, out_height);
2132 2134
2133 error = (error || in_width > maxsinglelinewidth * 2 || 2135 error = (error || in_width > maxsinglelinewidth * 2 ||
@@ -2145,7 +2147,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel,
2145 } 2147 }
2146 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); 2148 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2147 2149
2148 if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width, height, 2150 if (check_horiz_timing_omap3(plane, mgr_timings, pos_x, width, height,
2149 out_width, out_height)){ 2151 out_width, out_height)){
2150 DSSERR("horizontal timing too tight\n"); 2152 DSSERR("horizontal timing too tight\n");
2151 return -EINVAL; 2153 return -EINVAL;
@@ -2164,7 +2166,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel,
2164 return 0; 2166 return 0;
2165} 2167}
2166 2168
2167static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel, 2169static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
2168 const struct omap_video_timings *mgr_timings, 2170 const struct omap_video_timings *mgr_timings,
2169 u16 width, u16 height, u16 out_width, u16 out_height, 2171 u16 width, u16 height, u16 out_width, u16 out_height,
2170 enum omap_color_mode color_mode, bool *five_taps, 2172 enum omap_color_mode color_mode, bool *five_taps,
@@ -2176,9 +2178,10 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel,
2176 u16 in_height = DIV_ROUND_UP(height, *decim_y); 2178 u16 in_height = DIV_ROUND_UP(height, *decim_y);
2177 const int maxsinglelinewidth = 2179 const int maxsinglelinewidth =
2178 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); 2180 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2181 unsigned long pclk = dispc_plane_pclk_rate(plane);
2182
2183 in_width_max = dispc_core_clk_rate() / DIV_ROUND_UP(pclk, out_width);
2179 2184
2180 in_width_max = dispc_core_clk_rate() /
2181 DIV_ROUND_UP(dispc_mgr_pclk_rate(channel), out_width);
2182 *decim_x = DIV_ROUND_UP(width, in_width_max); 2185 *decim_x = DIV_ROUND_UP(width, in_width_max);
2183 2186
2184 *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min; 2187 *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min;
@@ -2195,13 +2198,13 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel,
2195 return -EINVAL; 2198 return -EINVAL;
2196 } 2199 }
2197 2200
2198 *core_clk = dispc.feat->calc_core_clk(channel, in_width, in_height, 2201 *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height,
2199 out_width, out_height); 2202 out_width, out_height);
2200 return 0; 2203 return 0;
2201} 2204}
2202 2205
2203static int dispc_ovl_calc_scaling(enum omap_plane plane, 2206static int dispc_ovl_calc_scaling(enum omap_plane plane,
2204 enum omap_overlay_caps caps, enum omap_channel channel, 2207 enum omap_overlay_caps caps,
2205 const struct omap_video_timings *mgr_timings, 2208 const struct omap_video_timings *mgr_timings,
2206 u16 width, u16 height, u16 out_width, u16 out_height, 2209 u16 width, u16 height, u16 out_width, u16 out_height,
2207 enum omap_color_mode color_mode, bool *five_taps, 2210 enum omap_color_mode color_mode, bool *five_taps,
@@ -2242,9 +2245,9 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2242 if (decim_y > *y_predecim || out_height > height * 8) 2245 if (decim_y > *y_predecim || out_height > height * 8)
2243 return -EINVAL; 2246 return -EINVAL;
2244 2247
2245 ret = dispc.feat->calc_scaling(channel, mgr_timings, width, height, 2248 ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height,
2246 out_width, out_height, color_mode, five_taps, x_predecim, 2249 out_width, out_height, color_mode, five_taps,
2247 y_predecim, &decim_x, &decim_y, pos_x, &core_clk); 2250 x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk);
2248 if (ret) 2251 if (ret)
2249 return ret; 2252 return ret;
2250 2253
@@ -2265,12 +2268,11 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2265} 2268}
2266 2269
2267static int dispc_ovl_setup_common(enum omap_plane plane, 2270static int dispc_ovl_setup_common(enum omap_plane plane,
2268 enum omap_channel channel, enum omap_overlay_caps caps, 2271 enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
2269 u32 paddr, u32 p_uv_addr, u16 screen_width, int pos_x, 2272 u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
2270 int pos_y, u16 width, u16 height, u16 out_width, u16 out_height, 2273 u16 out_width, u16 out_height, enum omap_color_mode color_mode,
2271 enum omap_color_mode color_mode, u8 rotation, bool mirror, 2274 u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
2272 u8 zorder, u8 pre_mult_alpha, u8 global_alpha, 2275 u8 global_alpha, enum omap_dss_rotation_type rotation_type,
2273 enum omap_dss_rotation_type rotation_type,
2274 bool replication, const struct omap_video_timings *mgr_timings) 2276 bool replication, const struct omap_video_timings *mgr_timings)
2275{ 2277{
2276 bool five_taps = true; 2278 bool five_taps = true;
@@ -2309,7 +2311,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
2309 if (!dss_feat_color_mode_supported(plane, color_mode)) 2311 if (!dss_feat_color_mode_supported(plane, color_mode))
2310 return -EINVAL; 2312 return -EINVAL;
2311 2313
2312 r = dispc_ovl_calc_scaling(plane, caps, channel, mgr_timings, in_width, 2314 r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width,
2313 in_height, out_width, out_height, color_mode, 2315 in_height, out_width, out_height, color_mode,
2314 &five_taps, &x_predecim, &y_predecim, pos_x, 2316 &five_taps, &x_predecim, &y_predecim, pos_x,
2315 rotation_type); 2317 rotation_type);
@@ -2424,12 +2426,11 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
2424 oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height, 2426 oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
2425 oi->color_mode, oi->rotation, oi->mirror, channel, replication); 2427 oi->color_mode, oi->rotation, oi->mirror, channel, replication);
2426 2428
2427 r = dispc_ovl_setup_common(plane, channel, ovl->caps, oi->paddr, 2429 r = dispc_ovl_setup_common(plane, ovl->caps, oi->paddr, oi->p_uv_addr,
2428 oi->p_uv_addr, oi->screen_width, oi->pos_x, oi->pos_y, 2430 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
2429 oi->width, oi->height, oi->out_width, oi->out_height, 2431 oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
2430 oi->color_mode, oi->rotation, oi->mirror, oi->zorder, 2432 oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
2431 oi->pre_mult_alpha, oi->global_alpha, oi->rotation_type, 2433 oi->rotation_type, replication, mgr_timings);
2432 replication, mgr_timings);
2433 2434
2434 return r; 2435 return r;
2435} 2436}
@@ -2989,6 +2990,23 @@ unsigned long dispc_core_clk_rate(void)
2989 return fclk / lcd; 2990 return fclk / lcd;
2990} 2991}
2991 2992
2993static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
2994{
2995 enum omap_channel channel = dispc_ovl_get_channel_out(plane);
2996
2997 return dispc_mgr_pclk_rate(channel);
2998}
2999
3000static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
3001{
3002 enum omap_channel channel = dispc_ovl_get_channel_out(plane);
3003
3004 if (dss_mgr_is_lcd(channel))
3005 return dispc_mgr_lclk_rate(channel);
3006 else
3007 return dispc_fclk_rate();
3008
3009}
2992static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel) 3010static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
2993{ 3011{
2994 int lcd, pcd; 3012 int lcd, pcd;