diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 110 |
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 | ||
238 | static void _omap_dispc_set_irqs(void); | 238 | static void _omap_dispc_set_irqs(void); |
239 | static unsigned long dispc_plane_pclk_rate(enum omap_plane plane); | ||
240 | static unsigned long dispc_plane_lclk_rate(enum omap_plane plane); | ||
239 | 241 | ||
240 | static inline void dispc_write_reg(const u16 idx, u32 val) | 242 | static 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 | */ |
1922 | static int check_horiz_timing_omap3(enum omap_channel channel, | 1924 | static 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 | ||
1974 | static unsigned long calc_core_clk_five_taps(enum omap_channel channel, | 1973 | static 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 | ||
2014 | static unsigned long calc_core_clk_24xx(enum omap_channel channel, u16 width, | 2014 | static 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 | ||
2025 | static unsigned long calc_core_clk_34xx(enum omap_channel channel, u16 width, | 2025 | static 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 | ||
2052 | static unsigned long calc_core_clk_44xx(enum omap_channel channel, u16 width, | 2052 | static 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 | ||
2063 | static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel, | 2063 | static 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 | ||
2103 | static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel, | 2104 | static 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 | ||
2167 | static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel, | 2169 | static 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 | ||
2203 | static int dispc_ovl_calc_scaling(enum omap_plane plane, | 2206 | static 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 | ||
2267 | static int dispc_ovl_setup_common(enum omap_plane plane, | 2270 | static 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 | ||
2993 | static 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 | |||
3000 | static 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 | } | ||
2992 | static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel) | 3010 | static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel) |
2993 | { | 3011 | { |
2994 | int lcd, pcd; | 3012 | int lcd, pcd; |