diff options
author | Mythri P K <mythripk@ti.com> | 2012-01-06 07:22:09 -0500 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-01-25 06:48:33 -0500 |
commit | 46095b2d96bac92c2cc5ca557ec7de73e13311ab (patch) | |
tree | 676e095506bc293d78472854cb79e84db664b983 /drivers/video/omap2 | |
parent | a05ce78f308fa22b6254995c25ff79e82a27de75 (diff) |
OMAPDSS: HDMI: change the timing match logic
Change the timing match logic, Instead of the statically mapped method
to get the corresponding timings for a given code and mode, move to a
simpler array indexed method. It will help to scale up to add more
timings when needed.
Signed-off-by: Mythri P K <mythripk@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video/omap2')
-rw-r--r-- | drivers/video/omap2/dss/hdmi.c | 176 |
1 files changed, 76 insertions, 100 deletions
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 266af264eb9b..6f027d30d5dd 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c | |||
@@ -58,8 +58,6 @@ | |||
58 | #define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 | 58 | #define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 |
59 | #define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 | 59 | #define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 |
60 | 60 | ||
61 | #define OMAP_HDMI_TIMINGS_NB 34 | ||
62 | |||
63 | #define HDMI_DEFAULT_REGN 16 | 61 | #define HDMI_DEFAULT_REGN 16 |
64 | #define HDMI_DEFAULT_REGM2 1 | 62 | #define HDMI_DEFAULT_REGM2 1 |
65 | 63 | ||
@@ -88,7 +86,7 @@ static struct { | |||
88 | * map it to corresponding CEA or VESA index. | 86 | * map it to corresponding CEA or VESA index. |
89 | */ | 87 | */ |
90 | 88 | ||
91 | static const struct hdmi_config cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = { | 89 | static const struct hdmi_config cea_timings[] = { |
92 | { {640, 480, 25200, 96, 16, 48, 2, 10, 33, 0, 0, 0}, {1, HDMI_HDMI} }, | 90 | { {640, 480, 25200, 96, 16, 48, 2, 10, 33, 0, 0, 0}, {1, HDMI_HDMI} }, |
93 | { {720, 480, 27027, 62, 16, 60, 6, 9, 30, 0, 0, 0}, {2, HDMI_HDMI} }, | 91 | { {720, 480, 27027, 62, 16, 60, 6, 9, 30, 0, 0, 0}, {2, HDMI_HDMI} }, |
94 | { {1280, 720, 74250, 40, 110, 220, 5, 5, 20, 1, 1, 0}, {4, HDMI_HDMI} }, | 92 | { {1280, 720, 74250, 40, 110, 220, 5, 5, 20, 1, 1, 0}, {4, HDMI_HDMI} }, |
@@ -104,6 +102,8 @@ static const struct hdmi_config cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = { | |||
104 | { {1920, 1080, 74250, 44, 638, 148, 5, 4, 36, 1, 1, 0}, {32, HDMI_HDMI} }, | 102 | { {1920, 1080, 74250, 44, 638, 148, 5, 4, 36, 1, 1, 0}, {32, HDMI_HDMI} }, |
105 | { {2880, 480, 108108, 248, 64, 240, 6, 9, 30, 0, 0, 0}, {35, HDMI_HDMI} }, | 103 | { {2880, 480, 108108, 248, 64, 240, 6, 9, 30, 0, 0, 0}, {35, HDMI_HDMI} }, |
106 | { {2880, 576, 108000, 256, 48, 272, 5, 5, 39, 0, 0, 0}, {37, HDMI_HDMI} }, | 104 | { {2880, 576, 108000, 256, 48, 272, 5, 5, 39, 0, 0, 0}, {37, HDMI_HDMI} }, |
105 | }; | ||
106 | static const struct hdmi_config vesa_timings[] = { | ||
107 | /* VESA From Here */ | 107 | /* VESA From Here */ |
108 | { {640, 480, 25175, 96, 16, 48, 2 , 11, 31, 0, 0, 0}, {4, HDMI_DVI} }, | 108 | { {640, 480, 25175, 96, 16, 48, 2 , 11, 31, 0, 0, 0}, {4, HDMI_DVI} }, |
109 | { {800, 600, 40000, 128, 40, 88, 4 , 1, 23, 1, 1, 0}, {9, HDMI_DVI} }, | 109 | { {800, 600, 40000, 128, 40, 88, 4 , 1, 23, 1, 1, 0}, {9, HDMI_DVI} }, |
@@ -126,39 +126,6 @@ static const struct hdmi_config cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = { | |||
126 | { {1280, 720, 74250, 40, 110, 220, 5, 5, 20, 1, 1, 0}, {0x55, HDMI_DVI} } | 126 | { {1280, 720, 74250, 40, 110, 220, 5, 5, 20, 1, 1, 0}, {0x55, HDMI_DVI} } |
127 | }; | 127 | }; |
128 | 128 | ||
129 | /* | ||
130 | * This is a static mapping array which maps the timing values | ||
131 | * with corresponding CEA / VESA code | ||
132 | */ | ||
133 | static const int code_index[OMAP_HDMI_TIMINGS_NB] = { | ||
134 | 1, 19, 4, 2, 37, 6, 21, 20, 5, 16, 17, 29, 31, 35, 32, | ||
135 | /* <--15 CEA 17--> vesa*/ | ||
136 | 4, 9, 0xE, 0x17, 0x1C, 0x27, 0x20, 0x23, 0x10, 0x2A, | ||
137 | 0X2F, 0x3A, 0X51, 0X52, 0x16, 0x29, 0x39, 0x1B | ||
138 | }; | ||
139 | |||
140 | /* | ||
141 | * This is reverse static mapping which maps the CEA / VESA code | ||
142 | * to the corresponding timing values | ||
143 | */ | ||
144 | static const int code_cea[39] = { | ||
145 | -1, 0, 3, 3, 2, 8, 5, 5, -1, -1, | ||
146 | -1, -1, -1, -1, -1, -1, 9, 10, 10, 1, | ||
147 | 7, 6, 6, -1, -1, -1, -1, -1, -1, 11, | ||
148 | 11, 12, 14, -1, -1, 13, 13, 4, 4 | ||
149 | }; | ||
150 | |||
151 | static const int code_vesa[85] = { | ||
152 | -1, -1, -1, -1, 15, -1, -1, -1, -1, 16, | ||
153 | -1, -1, -1, -1, 17, -1, 23, -1, -1, -1, | ||
154 | -1, -1, 29, 18, -1, -1, -1, 32, 19, -1, | ||
155 | -1, -1, 21, -1, -1, 22, -1, -1, -1, 20, | ||
156 | -1, 30, 24, -1, -1, -1, -1, 25, -1, -1, | ||
157 | -1, -1, -1, -1, -1, -1, -1, 31, 26, -1, | ||
158 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
159 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
160 | -1, 27, 28, -1, 33}; | ||
161 | |||
162 | static int hdmi_runtime_get(void) | 129 | static int hdmi_runtime_get(void) |
163 | { | 130 | { |
164 | int r; | 131 | int r; |
@@ -188,82 +155,83 @@ int hdmi_init_display(struct omap_dss_device *dssdev) | |||
188 | return 0; | 155 | return 0; |
189 | } | 156 | } |
190 | 157 | ||
191 | static int get_timings_index(void) | 158 | static const struct hdmi_config *hdmi_find_timing( |
159 | const struct hdmi_config *timings_arr, | ||
160 | int len) | ||
192 | { | 161 | { |
193 | int code; | 162 | int i; |
194 | 163 | ||
195 | if (hdmi.mode == 0) | 164 | for (i = 0; i < len; i++) { |
196 | code = code_vesa[hdmi.code]; | 165 | if (timings_arr[i].cm.code == hdmi.code) |
197 | else | 166 | return &timings_arr[i]; |
198 | code = code_cea[hdmi.code]; | 167 | } |
168 | return NULL; | ||
169 | } | ||
199 | 170 | ||
200 | if (code == -1) { | 171 | static const struct hdmi_config *hdmi_get_timings(void) |
201 | /* HDMI code 4 corresponds to 640 * 480 VGA */ | 172 | { |
202 | hdmi.code = 4; | 173 | const struct hdmi_config *arr; |
203 | /* DVI mode 1 corresponds to HDMI 0 to DVI */ | 174 | int len; |
204 | hdmi.mode = HDMI_DVI; | 175 | |
176 | if (hdmi.mode == HDMI_DVI) { | ||
177 | arr = vesa_timings; | ||
178 | len = ARRAY_SIZE(vesa_timings); | ||
179 | } else { | ||
180 | arr = cea_timings; | ||
181 | len = ARRAY_SIZE(cea_timings); | ||
182 | } | ||
183 | |||
184 | return hdmi_find_timing(arr, len); | ||
185 | } | ||
186 | |||
187 | static bool hdmi_timings_compare(struct omap_video_timings *timing1, | ||
188 | const struct hdmi_video_timings *timing2) | ||
189 | { | ||
190 | int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync; | ||
191 | |||
192 | if ((timing2->pixel_clock == timing1->pixel_clock) && | ||
193 | (timing2->x_res == timing1->x_res) && | ||
194 | (timing2->y_res == timing1->y_res)) { | ||
195 | |||
196 | timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp; | ||
197 | timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp; | ||
198 | timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp; | ||
199 | timing1_vsync = timing2->vfp + timing2->vsw + timing2->vbp; | ||
205 | 200 | ||
206 | code = code_vesa[hdmi.code]; | 201 | DSSDBG("timing1_hsync = %d timing1_vsync = %d"\ |
202 | "timing2_hsync = %d timing2_vsync = %d\n", | ||
203 | timing1_hsync, timing1_vsync, | ||
204 | timing2_hsync, timing2_vsync); | ||
205 | |||
206 | if ((timing1_hsync == timing2_hsync) && | ||
207 | (timing1_vsync == timing2_vsync)) { | ||
208 | return true; | ||
209 | } | ||
207 | } | 210 | } |
208 | return code; | 211 | return false; |
209 | } | 212 | } |
210 | 213 | ||
211 | static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) | 214 | static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) |
212 | { | 215 | { |
213 | int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0; | 216 | int i; |
214 | int timing_vsync = 0, timing_hsync = 0; | ||
215 | struct hdmi_video_timings temp; | ||
216 | struct hdmi_cm cm = {-1}; | 217 | struct hdmi_cm cm = {-1}; |
217 | DSSDBG("hdmi_get_code\n"); | 218 | DSSDBG("hdmi_get_code\n"); |
218 | 219 | ||
219 | for (i = 0; i < OMAP_HDMI_TIMINGS_NB; i++) { | 220 | for (i = 0; i < ARRAY_SIZE(cea_timings); i++) { |
220 | temp = cea_vesa_timings[i].timings; | 221 | if (hdmi_timings_compare(timing, &cea_timings[i].timings)) { |
221 | if ((temp.pixel_clock == timing->pixel_clock) && | 222 | cm = cea_timings[i].cm; |
222 | (temp.x_res == timing->x_res) && | 223 | goto end; |
223 | (temp.y_res == timing->y_res)) { | 224 | } |
224 | 225 | } | |
225 | temp_hsync = temp.hfp + temp.hsw + temp.hbp; | 226 | for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) { |
226 | timing_hsync = timing->hfp + timing->hsw + timing->hbp; | 227 | if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) { |
227 | temp_vsync = temp.vfp + temp.vsw + temp.vbp; | 228 | cm = vesa_timings[i].cm; |
228 | timing_vsync = timing->vfp + timing->vsw + timing->vbp; | 229 | goto end; |
229 | |||
230 | DSSDBG("temp_hsync = %d , temp_vsync = %d" | ||
231 | "timing_hsync = %d, timing_vsync = %d\n", | ||
232 | temp_hsync, temp_hsync, | ||
233 | timing_hsync, timing_vsync); | ||
234 | |||
235 | if ((temp_hsync == timing_hsync) && | ||
236 | (temp_vsync == timing_vsync)) { | ||
237 | code = i; | ||
238 | cm.code = code_index[i]; | ||
239 | if (code < 14) | ||
240 | cm.mode = HDMI_HDMI; | ||
241 | else | ||
242 | cm.mode = HDMI_DVI; | ||
243 | DSSDBG("Hdmi_code = %d mode = %d\n", | ||
244 | cm.code, cm.mode); | ||
245 | break; | ||
246 | } | ||
247 | } | 230 | } |
248 | } | 231 | } |
249 | 232 | ||
250 | return cm; | 233 | end: return cm; |
251 | } | ||
252 | 234 | ||
253 | static void update_hdmi_timings(struct hdmi_config *cfg, | ||
254 | struct omap_video_timings *timings, int code) | ||
255 | { | ||
256 | cfg->timings.x_res = timings->x_res; | ||
257 | cfg->timings.y_res = timings->y_res; | ||
258 | cfg->timings.hbp = timings->hbp; | ||
259 | cfg->timings.hfp = timings->hfp; | ||
260 | cfg->timings.hsw = timings->hsw; | ||
261 | cfg->timings.vbp = timings->vbp; | ||
262 | cfg->timings.vfp = timings->vfp; | ||
263 | cfg->timings.vsw = timings->vsw; | ||
264 | cfg->timings.pixel_clock = timings->pixel_clock; | ||
265 | cfg->timings.vsync_pol = cea_vesa_timings[code].timings.vsync_pol; | ||
266 | cfg->timings.hsync_pol = cea_vesa_timings[code].timings.hsync_pol; | ||
267 | } | 235 | } |
268 | 236 | ||
269 | unsigned long hdmi_get_pixel_clock(void) | 237 | unsigned long hdmi_get_pixel_clock(void) |
@@ -325,7 +293,8 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | |||
325 | 293 | ||
326 | static int hdmi_power_on(struct omap_dss_device *dssdev) | 294 | static int hdmi_power_on(struct omap_dss_device *dssdev) |
327 | { | 295 | { |
328 | int r, code = 0; | 296 | int r; |
297 | const struct hdmi_config *timing; | ||
329 | struct omap_video_timings *p; | 298 | struct omap_video_timings *p; |
330 | unsigned long phy; | 299 | unsigned long phy; |
331 | 300 | ||
@@ -341,9 +310,16 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
341 | dssdev->panel.timings.x_res, | 310 | dssdev->panel.timings.x_res, |
342 | dssdev->panel.timings.y_res); | 311 | dssdev->panel.timings.y_res); |
343 | 312 | ||
344 | code = get_timings_index(); | 313 | timing = hdmi_get_timings(); |
345 | update_hdmi_timings(&hdmi.ip_data.cfg, p, code); | 314 | if (timing == NULL) { |
346 | 315 | /* HDMI code 4 corresponds to 640 * 480 VGA */ | |
316 | hdmi.code = 4; | ||
317 | /* DVI mode 1 corresponds to HDMI 0 to DVI */ | ||
318 | hdmi.mode = HDMI_DVI; | ||
319 | hdmi.ip_data.cfg = vesa_timings[0]; | ||
320 | } else { | ||
321 | hdmi.ip_data.cfg = *timing; | ||
322 | } | ||
347 | phy = p->pixel_clock; | 323 | phy = p->pixel_clock; |
348 | 324 | ||
349 | hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); | 325 | hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); |