Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[pandora-kernel.git] / drivers / media / video / davinci / vpif.c
1 /*
2  * vpif - DM646x Video Port Interface driver
3  * VPIF is a receiver and transmitter for video data. It has two channels(0, 1)
4  * that receiveing video byte stream and two channels(2, 3) for video output.
5  * The hardware supports SDTV, HDTV formats, raw data capture.
6  * Currently, the driver supports NTSC and PAL standards.
7  *
8  * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation version 2.
13  *
14  * This program is distributed .as is. WITHOUT ANY WARRANTY of any
15  * kind, whether express or implied; without even the implied warranty
16  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  */
19
20 #include <linux/init.h>
21 #include <linux/module.h>
22 #include <linux/platform_device.h>
23 #include <linux/spinlock.h>
24 #include <linux/kernel.h>
25 #include <linux/io.h>
26 #include <mach/hardware.h>
27
28 #include "vpif.h"
29
30 MODULE_DESCRIPTION("TI DaVinci Video Port Interface driver");
31 MODULE_LICENSE("GPL");
32
33 #define VPIF_CH0_MAX_MODES      (22)
34 #define VPIF_CH1_MAX_MODES      (02)
35 #define VPIF_CH2_MAX_MODES      (15)
36 #define VPIF_CH3_MAX_MODES      (02)
37
38 static resource_size_t  res_len;
39 static struct resource  *res;
40 spinlock_t vpif_lock;
41
42 void __iomem *vpif_base;
43
44 /**
45  * ch_params: video standard configuration parameters for vpif
46  * The table must include all presets from supported subdevices.
47  */
48 const struct vpif_channel_config_params ch_params[] = {
49         /* HDTV formats */
50         {
51                 .name = "480p59_94",
52                 .width = 720,
53                 .height = 480,
54                 .frm_fmt = 1,
55                 .ycmux_mode = 0,
56                 .eav2sav = 138-8,
57                 .sav2eav = 720,
58                 .l1 = 1,
59                 .l3 = 43,
60                 .l5 = 523,
61                 .vsize = 525,
62                 .capture_format = 0,
63                 .vbi_supported = 0,
64                 .hd_sd = 1,
65                 .dv_preset = V4L2_DV_480P59_94,
66         },
67         {
68                 .name = "576p50",
69                 .width = 720,
70                 .height = 576,
71                 .frm_fmt = 1,
72                 .ycmux_mode = 0,
73                 .eav2sav = 144-8,
74                 .sav2eav = 720,
75                 .l1 = 1,
76                 .l3 = 45,
77                 .l5 = 621,
78                 .vsize = 625,
79                 .capture_format = 0,
80                 .vbi_supported = 0,
81                 .hd_sd = 1,
82                 .dv_preset = V4L2_DV_576P50,
83         },
84         {
85                 .name = "720p50",
86                 .width = 1280,
87                 .height = 720,
88                 .frm_fmt = 1,
89                 .ycmux_mode = 0,
90                 .eav2sav = 700-8,
91                 .sav2eav = 1280,
92                 .l1 = 1,
93                 .l3 = 26,
94                 .l5 = 746,
95                 .vsize = 750,
96                 .capture_format = 0,
97                 .vbi_supported = 0,
98                 .hd_sd = 1,
99                 .dv_preset = V4L2_DV_720P50,
100         },
101         {
102                 .name = "720p60",
103                 .width = 1280,
104                 .height = 720,
105                 .frm_fmt = 1,
106                 .ycmux_mode = 0,
107                 .eav2sav = 370 - 8,
108                 .sav2eav = 1280,
109                 .l1 = 1,
110                 .l3 = 26,
111                 .l5 = 746,
112                 .vsize = 750,
113                 .capture_format = 0,
114                 .vbi_supported = 0,
115                 .hd_sd = 1,
116                 .dv_preset = V4L2_DV_720P60,
117         },
118         {
119                 .name = "1080I50",
120                 .width = 1920,
121                 .height = 1080,
122                 .frm_fmt = 0,
123                 .ycmux_mode = 0,
124                 .eav2sav = 720 - 8,
125                 .sav2eav = 1920,
126                 .l1 = 1,
127                 .l3 = 21,
128                 .l5 = 561,
129                 .l7 = 563,
130                 .l9 = 584,
131                 .l11 = 1124,
132                 .vsize = 1125,
133                 .capture_format = 0,
134                 .vbi_supported = 0,
135                 .hd_sd = 1,
136                 .dv_preset = V4L2_DV_1080I50,
137         },
138         {
139                 .name = "1080I60",
140                 .width = 1920,
141                 .height = 1080,
142                 .frm_fmt = 0,
143                 .ycmux_mode = 0,
144                 .eav2sav = 280 - 8,
145                 .sav2eav = 1920,
146                 .l1 = 1,
147                 .l3 = 21,
148                 .l5 = 561,
149                 .l7 = 563,
150                 .l9 = 584,
151                 .l11 = 1124,
152                 .vsize = 1125,
153                 .capture_format = 0,
154                 .vbi_supported = 0,
155                 .hd_sd = 1,
156                 .dv_preset = V4L2_DV_1080I60,
157         },
158         {
159                 .name = "1080p60",
160                 .width = 1920,
161                 .height = 1080,
162                 .frm_fmt = 1,
163                 .ycmux_mode = 0,
164                 .eav2sav = 280 - 8,
165                 .sav2eav = 1920,
166                 .l1 = 1,
167                 .l3 = 42,
168                 .l5 = 1122,
169                 .vsize = 1125,
170                 .capture_format = 0,
171                 .vbi_supported = 0,
172                 .hd_sd = 1,
173                 .dv_preset = V4L2_DV_1080P60,
174         },
175
176         /* SDTV formats */
177         {
178                 .name = "NTSC_M",
179                 .width = 720,
180                 .height = 480,
181                 .frm_fmt = 0,
182                 .ycmux_mode = 1,
183                 .eav2sav = 268,
184                 .sav2eav = 1440,
185                 .l1 = 1,
186                 .l3 = 23,
187                 .l5 = 263,
188                 .l7 = 266,
189                 .l9 = 286,
190                 .l11 = 525,
191                 .vsize = 525,
192                 .capture_format = 0,
193                 .vbi_supported = 1,
194                 .hd_sd = 0,
195                 .stdid = V4L2_STD_525_60,
196         },
197         {
198                 .name = "PAL_BDGHIK",
199                 .width = 720,
200                 .height = 576,
201                 .frm_fmt = 0,
202                 .ycmux_mode = 1,
203                 .eav2sav = 280,
204                 .sav2eav = 1440,
205                 .l1 = 1,
206                 .l3 = 23,
207                 .l5 = 311,
208                 .l7 = 313,
209                 .l9 = 336,
210                 .l11 = 624,
211                 .vsize = 625,
212                 .capture_format = 0,
213                 .vbi_supported = 1,
214                 .hd_sd = 0,
215                 .stdid = V4L2_STD_625_50,
216         },
217 };
218
219 const unsigned int vpif_ch_params_count = ARRAY_SIZE(ch_params);
220
221 static inline void vpif_wr_bit(u32 reg, u32 bit, u32 val)
222 {
223         if (val)
224                 vpif_set_bit(reg, bit);
225         else
226                 vpif_clr_bit(reg, bit);
227 }
228
229 /* This structure is used to keep track of VPIF size register's offsets */
230 struct vpif_registers {
231         u32 h_cfg, v_cfg_00, v_cfg_01, v_cfg_02, v_cfg, ch_ctrl;
232         u32 line_offset, vanc0_strt, vanc0_size, vanc1_strt;
233         u32 vanc1_size, width_mask, len_mask;
234         u8 max_modes;
235 };
236
237 static const struct vpif_registers vpifregs[VPIF_NUM_CHANNELS] = {
238         /* Channel0 */
239         {
240                 VPIF_CH0_H_CFG, VPIF_CH0_V_CFG_00, VPIF_CH0_V_CFG_01,
241                 VPIF_CH0_V_CFG_02, VPIF_CH0_V_CFG_03, VPIF_CH0_CTRL,
242                 VPIF_CH0_IMG_ADD_OFST, 0, 0, 0, 0, 0x1FFF, 0xFFF,
243                 VPIF_CH0_MAX_MODES,
244         },
245         /* Channel1 */
246         {
247                 VPIF_CH1_H_CFG, VPIF_CH1_V_CFG_00, VPIF_CH1_V_CFG_01,
248                 VPIF_CH1_V_CFG_02, VPIF_CH1_V_CFG_03, VPIF_CH1_CTRL,
249                 VPIF_CH1_IMG_ADD_OFST, 0, 0, 0, 0, 0x1FFF, 0xFFF,
250                 VPIF_CH1_MAX_MODES,
251         },
252         /* Channel2 */
253         {
254                 VPIF_CH2_H_CFG, VPIF_CH2_V_CFG_00, VPIF_CH2_V_CFG_01,
255                 VPIF_CH2_V_CFG_02, VPIF_CH2_V_CFG_03, VPIF_CH2_CTRL,
256                 VPIF_CH2_IMG_ADD_OFST, VPIF_CH2_VANC0_STRT, VPIF_CH2_VANC0_SIZE,
257                 VPIF_CH2_VANC1_STRT, VPIF_CH2_VANC1_SIZE, 0x7FF, 0x7FF,
258                 VPIF_CH2_MAX_MODES
259         },
260         /* Channel3 */
261         {
262                 VPIF_CH3_H_CFG, VPIF_CH3_V_CFG_00, VPIF_CH3_V_CFG_01,
263                 VPIF_CH3_V_CFG_02, VPIF_CH3_V_CFG_03, VPIF_CH3_CTRL,
264                 VPIF_CH3_IMG_ADD_OFST, VPIF_CH3_VANC0_STRT, VPIF_CH3_VANC0_SIZE,
265                 VPIF_CH3_VANC1_STRT, VPIF_CH3_VANC1_SIZE, 0x7FF, 0x7FF,
266                 VPIF_CH3_MAX_MODES
267         },
268 };
269
270 /* vpif_set_mode_info:
271  * This function is used to set horizontal and vertical config parameters
272  * As per the standard in the channel, configure the values of L1, L3,
273  * L5, L7  L9, L11 in VPIF Register , also write width and height
274  */
275 static void vpif_set_mode_info(const struct vpif_channel_config_params *config,
276                                 u8 channel_id, u8 config_channel_id)
277 {
278         u32 value;
279
280         value = (config->eav2sav & vpifregs[config_channel_id].width_mask);
281         value <<= VPIF_CH_LEN_SHIFT;
282         value |= (config->sav2eav & vpifregs[config_channel_id].width_mask);
283         regw(value, vpifregs[channel_id].h_cfg);
284
285         value = (config->l1 & vpifregs[config_channel_id].len_mask);
286         value <<= VPIF_CH_LEN_SHIFT;
287         value |= (config->l3 & vpifregs[config_channel_id].len_mask);
288         regw(value, vpifregs[channel_id].v_cfg_00);
289
290         value = (config->l5 & vpifregs[config_channel_id].len_mask);
291         value <<= VPIF_CH_LEN_SHIFT;
292         value |= (config->l7 & vpifregs[config_channel_id].len_mask);
293         regw(value, vpifregs[channel_id].v_cfg_01);
294
295         value = (config->l9 & vpifregs[config_channel_id].len_mask);
296         value <<= VPIF_CH_LEN_SHIFT;
297         value |= (config->l11 & vpifregs[config_channel_id].len_mask);
298         regw(value, vpifregs[channel_id].v_cfg_02);
299
300         value = (config->vsize & vpifregs[config_channel_id].len_mask);
301         regw(value, vpifregs[channel_id].v_cfg);
302 }
303
304 /* config_vpif_params
305  * Function to set the parameters of a channel
306  * Mainly modifies the channel ciontrol register
307  * It sets frame format, yc mux mode
308  */
309 static void config_vpif_params(struct vpif_params *vpifparams,
310                                 u8 channel_id, u8 found)
311 {
312         const struct vpif_channel_config_params *config = &vpifparams->std_info;
313         u32 value, ch_nip, reg;
314         u8 start, end;
315         int i;
316
317         start = channel_id;
318         end = channel_id + found;
319
320         for (i = start; i < end; i++) {
321                 reg = vpifregs[i].ch_ctrl;
322                 if (channel_id < 2)
323                         ch_nip = VPIF_CAPTURE_CH_NIP;
324                 else
325                         ch_nip = VPIF_DISPLAY_CH_NIP;
326
327                 vpif_wr_bit(reg, ch_nip, config->frm_fmt);
328                 vpif_wr_bit(reg, VPIF_CH_YC_MUX_BIT, config->ycmux_mode);
329                 vpif_wr_bit(reg, VPIF_CH_INPUT_FIELD_FRAME_BIT,
330                                         vpifparams->video_params.storage_mode);
331
332                 /* Set raster scanning SDR Format */
333                 vpif_clr_bit(reg, VPIF_CH_SDR_FMT_BIT);
334                 vpif_wr_bit(reg, VPIF_CH_DATA_MODE_BIT, config->capture_format);
335
336                 if (channel_id > 1)     /* Set the Pixel enable bit */
337                         vpif_set_bit(reg, VPIF_DISPLAY_PIX_EN_BIT);
338                 else if (config->capture_format) {
339                         /* Set the polarity of various pins */
340                         vpif_wr_bit(reg, VPIF_CH_FID_POLARITY_BIT,
341                                         vpifparams->iface.fid_pol);
342                         vpif_wr_bit(reg, VPIF_CH_V_VALID_POLARITY_BIT,
343                                         vpifparams->iface.vd_pol);
344                         vpif_wr_bit(reg, VPIF_CH_H_VALID_POLARITY_BIT,
345                                         vpifparams->iface.hd_pol);
346
347                         value = regr(reg);
348                         /* Set data width */
349                         value &= ((~(unsigned int)(0x3)) <<
350                                         VPIF_CH_DATA_WIDTH_BIT);
351                         value |= ((vpifparams->params.data_sz) <<
352                                                      VPIF_CH_DATA_WIDTH_BIT);
353                         regw(value, reg);
354                 }
355
356                 /* Write the pitch in the driver */
357                 regw((vpifparams->video_params.hpitch),
358                                                 vpifregs[i].line_offset);
359         }
360 }
361
362 /* vpif_set_video_params
363  * This function is used to set video parameters in VPIF register
364  */
365 int vpif_set_video_params(struct vpif_params *vpifparams, u8 channel_id)
366 {
367         const struct vpif_channel_config_params *config = &vpifparams->std_info;
368         int found = 1;
369
370         vpif_set_mode_info(config, channel_id, channel_id);
371         if (!config->ycmux_mode) {
372                 /* YC are on separate channels (HDTV formats) */
373                 vpif_set_mode_info(config, channel_id + 1, channel_id);
374                 found = 2;
375         }
376
377         config_vpif_params(vpifparams, channel_id, found);
378
379         regw(0x80, VPIF_REQ_SIZE);
380         regw(0x01, VPIF_EMULATION_CTRL);
381
382         return found;
383 }
384 EXPORT_SYMBOL(vpif_set_video_params);
385
386 void vpif_set_vbi_display_params(struct vpif_vbi_params *vbiparams,
387                                 u8 channel_id)
388 {
389         u32 value;
390
391         value = 0x3F8 & (vbiparams->hstart0);
392         value |= 0x3FFFFFF & ((vbiparams->vstart0) << 16);
393         regw(value, vpifregs[channel_id].vanc0_strt);
394
395         value = 0x3F8 & (vbiparams->hstart1);
396         value |= 0x3FFFFFF & ((vbiparams->vstart1) << 16);
397         regw(value, vpifregs[channel_id].vanc1_strt);
398
399         value = 0x3F8 & (vbiparams->hsize0);
400         value |= 0x3FFFFFF & ((vbiparams->vsize0) << 16);
401         regw(value, vpifregs[channel_id].vanc0_size);
402
403         value = 0x3F8 & (vbiparams->hsize1);
404         value |= 0x3FFFFFF & ((vbiparams->vsize1) << 16);
405         regw(value, vpifregs[channel_id].vanc1_size);
406
407 }
408 EXPORT_SYMBOL(vpif_set_vbi_display_params);
409
410 int vpif_channel_getfid(u8 channel_id)
411 {
412         return (regr(vpifregs[channel_id].ch_ctrl) & VPIF_CH_FID_MASK)
413                                         >> VPIF_CH_FID_SHIFT;
414 }
415 EXPORT_SYMBOL(vpif_channel_getfid);
416
417 static int __init vpif_probe(struct platform_device *pdev)
418 {
419         int status = 0;
420
421         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
422         if (!res)
423                 return -ENOENT;
424
425         res_len = res->end - res->start + 1;
426
427         res = request_mem_region(res->start, res_len, res->name);
428         if (!res)
429                 return -EBUSY;
430
431         vpif_base = ioremap(res->start, res_len);
432         if (!vpif_base) {
433                 status = -EBUSY;
434                 goto fail;
435         }
436
437         spin_lock_init(&vpif_lock);
438         dev_info(&pdev->dev, "vpif probe success\n");
439         return 0;
440
441 fail:
442         release_mem_region(res->start, res_len);
443         return status;
444 }
445
446 static int __devexit vpif_remove(struct platform_device *pdev)
447 {
448         iounmap(vpif_base);
449         release_mem_region(res->start, res_len);
450         return 0;
451 }
452
453 static struct platform_driver vpif_driver = {
454         .driver = {
455                 .name   = "vpif",
456                 .owner = THIS_MODULE,
457         },
458         .remove = __devexit_p(vpif_remove),
459         .probe = vpif_probe,
460 };
461
462 static void vpif_exit(void)
463 {
464         platform_driver_unregister(&vpif_driver);
465 }
466
467 static int __init vpif_init(void)
468 {
469         return platform_driver_register(&vpif_driver);
470 }
471 subsys_initcall(vpif_init);
472 module_exit(vpif_exit);
473