Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vpbe.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010 Texas Instruments Inc
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation version 2.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  */
17 #include <linux/kernel.h>
18 #include <linux/init.h>
19 #include <linux/module.h>
20 #include <linux/errno.h>
21 #include <linux/fs.h>
22 #include <linux/string.h>
23 #include <linux/wait.h>
24 #include <linux/time.h>
25 #include <linux/platform_device.h>
26 #include <linux/io.h>
27 #include <linux/slab.h>
28 #include <linux/clk.h>
29 #include <linux/err.h>
30 
31 #include <media/v4l2-device.h>
33 #include <media/davinci/vpbe.h>
34 #include <media/davinci/vpss.h>
36 
37 #define VPBE_DEFAULT_OUTPUT "Composite"
38 #define VPBE_DEFAULT_MODE "ntsc"
39 
40 static char *def_output = VPBE_DEFAULT_OUTPUT;
41 static char *def_mode = VPBE_DEFAULT_MODE;
42 static int debug;
43 
44 module_param(def_output, charp, S_IRUGO);
45 module_param(def_mode, charp, S_IRUGO);
46 module_param(debug, int, 0644);
47 
48 MODULE_PARM_DESC(def_output, "vpbe output name (default:Composite)");
49 MODULE_PARM_DESC(def_mode, "vpbe output mode name (default:ntsc");
50 MODULE_PARM_DESC(debug, "Debug level 0-1");
51 
52 MODULE_DESCRIPTION("TI DMXXX VPBE Display controller");
53 MODULE_LICENSE("GPL");
54 MODULE_AUTHOR("Texas Instruments");
55 
62 static struct encoder_config_info*
63 vpbe_current_encoder_info(struct vpbe_device *vpbe_dev)
64 {
65  struct vpbe_config *cfg = vpbe_dev->cfg;
66  int index = vpbe_dev->current_sd_index;
67 
68  return ((index == 0) ? &cfg->venc :
69  &cfg->ext_encoders[index-1]);
70 }
71 
80 static int vpbe_find_encoder_sd_index(struct vpbe_config *cfg,
81  int index)
82 {
83  char *encoder_name = cfg->outputs[index].subdev_name;
84  int i;
85 
86  /* Venc is always first */
87  if (!strcmp(encoder_name, cfg->venc.module_name))
88  return 0;
89 
90  for (i = 0; i < cfg->num_ext_encoders; i++) {
91  if (!strcmp(encoder_name,
92  cfg->ext_encoders[i].module_name))
93  return i+1;
94  }
95 
96  return -EINVAL;
97 }
98 
107 static int vpbe_g_cropcap(struct vpbe_device *vpbe_dev,
108  struct v4l2_cropcap *cropcap)
109 {
110  if (NULL == cropcap)
111  return -EINVAL;
112  cropcap->bounds.left = 0;
113  cropcap->bounds.top = 0;
114  cropcap->bounds.width = vpbe_dev->current_timings.xres;
115  cropcap->bounds.height = vpbe_dev->current_timings.yres;
116  cropcap->defrect = cropcap->bounds;
117 
118  return 0;
119 }
120 
129 static int vpbe_enum_outputs(struct vpbe_device *vpbe_dev,
130  struct v4l2_output *output)
131 {
132  struct vpbe_config *cfg = vpbe_dev->cfg;
133  int temp_index = output->index;
134 
135  if (temp_index >= cfg->num_outputs)
136  return -EINVAL;
137 
138  *output = cfg->outputs[temp_index].output;
139  output->index = temp_index;
140 
141  return 0;
142 }
143 
144 static int vpbe_get_mode_info(struct vpbe_device *vpbe_dev, char *mode,
145  int output_index)
146 {
147  struct vpbe_config *cfg = vpbe_dev->cfg;
148  struct vpbe_enc_mode_info var;
149  int curr_output = output_index;
150  int i;
151 
152  if (NULL == mode)
153  return -EINVAL;
154 
155  for (i = 0; i < cfg->outputs[curr_output].num_modes; i++) {
156  var = cfg->outputs[curr_output].modes[i];
157  if (!strcmp(mode, var.name)) {
158  vpbe_dev->current_timings = var;
159  return 0;
160  }
161  }
162 
163  return -EINVAL;
164 }
165 
166 static int vpbe_get_current_mode_info(struct vpbe_device *vpbe_dev,
168 {
169  if (NULL == mode_info)
170  return -EINVAL;
171 
172  *mode_info = vpbe_dev->current_timings;
173 
174  return 0;
175 }
176 
177 /* Get std by std id */
178 static int vpbe_get_std_info(struct vpbe_device *vpbe_dev,
180 {
181  struct vpbe_config *cfg = vpbe_dev->cfg;
182  struct vpbe_enc_mode_info var;
183  int curr_output = vpbe_dev->current_out_index;
184  int i;
185 
186  for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
187  var = cfg->outputs[curr_output].modes[i];
188  if ((var.timings_type & VPBE_ENC_STD) &&
189  (var.std_id & std_id)) {
190  vpbe_dev->current_timings = var;
191  return 0;
192  }
193  }
194 
195  return -EINVAL;
196 }
197 
198 static int vpbe_get_std_info_by_name(struct vpbe_device *vpbe_dev,
199  char *std_name)
200 {
201  struct vpbe_config *cfg = vpbe_dev->cfg;
202  struct vpbe_enc_mode_info var;
203  int curr_output = vpbe_dev->current_out_index;
204  int i;
205 
206  for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
207  var = cfg->outputs[curr_output].modes[i];
208  if (!strcmp(var.name, std_name)) {
209  vpbe_dev->current_timings = var;
210  return 0;
211  }
212  }
213 
214  return -EINVAL;
215 }
216 
224 static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index)
225 {
226  struct encoder_config_info *curr_enc_info =
227  vpbe_current_encoder_info(vpbe_dev);
228  struct vpbe_config *cfg = vpbe_dev->cfg;
229  struct venc_platform_data *venc_device = vpbe_dev->venc_device;
230  enum v4l2_mbus_pixelcode if_params;
231  int enc_out_index;
232  int sd_index;
233  int ret = 0;
234 
235  if (index >= cfg->num_outputs)
236  return -EINVAL;
237 
238  mutex_lock(&vpbe_dev->lock);
239 
240  sd_index = vpbe_dev->current_sd_index;
241  enc_out_index = cfg->outputs[index].output.index;
242  /*
243  * Currently we switch the encoder based on output selected
244  * by the application. If media controller is implemented later
245  * there is will be an API added to setup_link between venc
246  * and external encoder. So in that case below comparison always
247  * match and encoder will not be switched. But if application
248  * chose not to use media controller, then this provides current
249  * way of switching encoder at the venc output.
250  */
251  if (strcmp(curr_enc_info->module_name,
252  cfg->outputs[index].subdev_name)) {
253  /* Need to switch the encoder at the output */
254  sd_index = vpbe_find_encoder_sd_index(cfg, index);
255  if (sd_index < 0) {
256  ret = -EINVAL;
257  goto out;
258  }
259 
260  if_params = cfg->outputs[index].if_params;
261  venc_device->setup_if_config(if_params);
262  if (ret)
263  goto out;
264  }
265 
266  /* Set output at the encoder */
267  ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
268  s_routing, 0, enc_out_index, 0);
269  if (ret)
270  goto out;
271 
272  /*
273  * It is assumed that venc or extenal encoder will set a default
274  * mode in the sub device. For external encoder or LCD pannel output,
275  * we also need to set up the lcd port for the required mode. So setup
276  * the lcd port for the default mode that is configured in the board
277  * arch/arm/mach-davinci/board-dm355-evm.setup file for the external
278  * encoder.
279  */
280  ret = vpbe_get_mode_info(vpbe_dev,
281  cfg->outputs[index].default_mode, index);
282  if (!ret) {
283  struct osd_state *osd_device = vpbe_dev->osd_device;
284 
285  osd_device->ops.set_left_margin(osd_device,
286  vpbe_dev->current_timings.left_margin);
287  osd_device->ops.set_top_margin(osd_device,
288  vpbe_dev->current_timings.upper_margin);
289  vpbe_dev->current_sd_index = sd_index;
290  vpbe_dev->current_out_index = index;
291  }
292 out:
293  mutex_unlock(&vpbe_dev->lock);
294  return ret;
295 }
296 
297 static int vpbe_set_default_output(struct vpbe_device *vpbe_dev)
298 {
299  struct vpbe_config *cfg = vpbe_dev->cfg;
300  int ret = 0;
301  int i;
302 
303  for (i = 0; i < cfg->num_outputs; i++) {
304  if (!strcmp(def_output,
305  cfg->outputs[i].output.name)) {
306  ret = vpbe_set_output(vpbe_dev, i);
307  if (!ret)
308  vpbe_dev->current_out_index = i;
309  return ret;
310  }
311  }
312  return ret;
313 }
314 
321 static unsigned int vpbe_get_output(struct vpbe_device *vpbe_dev)
322 {
323  return vpbe_dev->current_out_index;
324 }
325 
332 static int vpbe_s_dv_timings(struct vpbe_device *vpbe_dev,
333  struct v4l2_dv_timings *dv_timings)
334 {
335  struct vpbe_config *cfg = vpbe_dev->cfg;
336  int out_index = vpbe_dev->current_out_index;
337  struct vpbe_output *output = &cfg->outputs[out_index];
338  int sd_index = vpbe_dev->current_sd_index;
339  int ret, i;
340 
341 
342  if (!(cfg->outputs[out_index].output.capabilities &
344  return -EINVAL;
345 
346  for (i = 0; i < output->num_modes; i++) {
347  if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS &&
348  !memcmp(&output->modes[i].dv_timings,
349  dv_timings, sizeof(*dv_timings)))
350  break;
351  }
352  if (i >= output->num_modes)
353  return -EINVAL;
354  vpbe_dev->current_timings = output->modes[i];
355  mutex_lock(&vpbe_dev->lock);
356 
357  ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
358  s_dv_timings, dv_timings);
359  if (!ret && (vpbe_dev->amp != NULL)) {
360  /* Call amplifier subdevice */
361  ret = v4l2_subdev_call(vpbe_dev->amp, video,
362  s_dv_timings, dv_timings);
363  }
364  /* set the lcd controller output for the given mode */
365  if (!ret) {
366  struct osd_state *osd_device = vpbe_dev->osd_device;
367 
368  osd_device->ops.set_left_margin(osd_device,
369  vpbe_dev->current_timings.left_margin);
370  osd_device->ops.set_top_margin(osd_device,
371  vpbe_dev->current_timings.upper_margin);
372  }
373  mutex_unlock(&vpbe_dev->lock);
374 
375  return ret;
376 }
377 
384 static int vpbe_g_dv_timings(struct vpbe_device *vpbe_dev,
385  struct v4l2_dv_timings *dv_timings)
386 {
387  if (vpbe_dev->current_timings.timings_type &
389  *dv_timings = vpbe_dev->current_timings.dv_timings;
390  return 0;
391  }
392 
393  return -EINVAL;
394 }
395 
402 static int vpbe_enum_dv_timings(struct vpbe_device *vpbe_dev,
403  struct v4l2_enum_dv_timings *timings)
404 {
405  struct vpbe_config *cfg = vpbe_dev->cfg;
406  int out_index = vpbe_dev->current_out_index;
407  struct vpbe_output *output = &cfg->outputs[out_index];
408  int j = 0;
409  int i;
410 
411  if (!(output->output.capabilities & V4L2_OUT_CAP_DV_TIMINGS))
412  return -EINVAL;
413 
414  for (i = 0; i < output->num_modes; i++) {
415  if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS) {
416  if (j == timings->index)
417  break;
418  j++;
419  }
420  }
421 
422  if (i == output->num_modes)
423  return -EINVAL;
424  timings->timings = output->modes[i].dv_timings;
425  return 0;
426 }
427 
434 static int vpbe_s_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
435 {
436  struct vpbe_config *cfg = vpbe_dev->cfg;
437  int out_index = vpbe_dev->current_out_index;
438  int sd_index = vpbe_dev->current_sd_index;
439  int ret;
440 
441  if (!(cfg->outputs[out_index].output.capabilities &
443  return -EINVAL;
444 
445  ret = vpbe_get_std_info(vpbe_dev, *std_id);
446  if (ret)
447  return ret;
448 
449  mutex_lock(&vpbe_dev->lock);
450 
451  ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
452  s_std_output, *std_id);
453  /* set the lcd controller output for the given mode */
454  if (!ret) {
455  struct osd_state *osd_device = vpbe_dev->osd_device;
456 
457  osd_device->ops.set_left_margin(osd_device,
458  vpbe_dev->current_timings.left_margin);
459  osd_device->ops.set_top_margin(osd_device,
460  vpbe_dev->current_timings.upper_margin);
461  }
462  mutex_unlock(&vpbe_dev->lock);
463 
464  return ret;
465 }
466 
473 static int vpbe_g_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
474 {
475  struct vpbe_enc_mode_info *cur_timings = &vpbe_dev->current_timings;
476 
477  if (cur_timings->timings_type & VPBE_ENC_STD) {
478  *std_id = cur_timings->std_id;
479  return 0;
480  }
481 
482  return -EINVAL;
483 }
484 
492 static int vpbe_set_mode(struct vpbe_device *vpbe_dev,
493  struct vpbe_enc_mode_info *mode_info)
494 {
495  struct vpbe_enc_mode_info *preset_mode = NULL;
496  struct vpbe_config *cfg = vpbe_dev->cfg;
497  struct v4l2_dv_timings dv_timings;
498  struct osd_state *osd_device;
499  int out_index = vpbe_dev->current_out_index;
500  int ret = 0;
501  int i;
502 
503  if ((NULL == mode_info) || (NULL == mode_info->name))
504  return -EINVAL;
505 
506  for (i = 0; i < cfg->outputs[out_index].num_modes; i++) {
507  if (!strcmp(mode_info->name,
508  cfg->outputs[out_index].modes[i].name)) {
509  preset_mode = &cfg->outputs[out_index].modes[i];
510  /*
511  * it may be one of the 3 timings type. Check and
512  * invoke right API
513  */
514  if (preset_mode->timings_type & VPBE_ENC_STD)
515  return vpbe_s_std(vpbe_dev,
516  &preset_mode->std_id);
517  if (preset_mode->timings_type &
519  dv_timings =
520  preset_mode->dv_timings;
521  return vpbe_s_dv_timings(vpbe_dev, &dv_timings);
522  }
523  }
524  }
525 
526  /* Only custom timing should reach here */
527  if (preset_mode == NULL)
528  return -EINVAL;
529 
530  mutex_lock(&vpbe_dev->lock);
531 
532  osd_device = vpbe_dev->osd_device;
533  vpbe_dev->current_timings = *preset_mode;
534  osd_device->ops.set_left_margin(osd_device,
535  vpbe_dev->current_timings.left_margin);
536  osd_device->ops.set_top_margin(osd_device,
537  vpbe_dev->current_timings.upper_margin);
538 
539  mutex_unlock(&vpbe_dev->lock);
540 
541  return ret;
542 }
543 
544 static int vpbe_set_default_mode(struct vpbe_device *vpbe_dev)
545 {
546  int ret;
547 
548  ret = vpbe_get_std_info_by_name(vpbe_dev, def_mode);
549  if (ret)
550  return ret;
551 
552  /* set the default mode in the encoder */
553  return vpbe_set_mode(vpbe_dev, &vpbe_dev->current_timings);
554 }
555 
556 static int platform_device_get(struct device *dev, void *data)
557 {
558  struct platform_device *pdev = to_platform_device(dev);
559  struct vpbe_device *vpbe_dev = data;
560 
561  if (strcmp("vpbe-osd", pdev->name) == 0)
562  vpbe_dev->osd_device = platform_get_drvdata(pdev);
563  if (strcmp("vpbe-venc", pdev->name) == 0)
564  vpbe_dev->venc_device = dev_get_platdata(&pdev->dev);
565 
566  return 0;
567 }
568 
580 static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
581 {
582  struct encoder_config_info *enc_info;
583  struct amp_config_info *amp_info;
584  struct v4l2_subdev **enc_subdev;
585  struct osd_state *osd_device;
586  struct i2c_adapter *i2c_adap;
587  int output_index;
588  int num_encoders;
589  int ret = 0;
590  int err;
591  int i;
592 
593  /*
594  * v4l2 abd FBDev frame buffer devices will get the vpbe_dev pointer
595  * from the platform device by iteration of platform drivers and
596  * matching with device name
597  */
598  if (NULL == vpbe_dev || NULL == dev) {
599  printk(KERN_ERR "Null device pointers.\n");
600  return -ENODEV;
601  }
602 
603  if (vpbe_dev->initialized)
604  return 0;
605 
606  mutex_lock(&vpbe_dev->lock);
607 
608  if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) {
609  /* We have dac clock available for platform */
610  vpbe_dev->dac_clk = clk_get(vpbe_dev->pdev, "vpss_dac");
611  if (IS_ERR(vpbe_dev->dac_clk)) {
612  ret = PTR_ERR(vpbe_dev->dac_clk);
613  goto fail_mutex_unlock;
614  }
615  if (clk_enable(vpbe_dev->dac_clk)) {
616  ret = -ENODEV;
617  goto fail_mutex_unlock;
618  }
619  }
620 
621  /* first enable vpss clocks */
623 
624  /* First register a v4l2 device */
625  ret = v4l2_device_register(dev, &vpbe_dev->v4l2_dev);
626  if (ret) {
627  v4l2_err(dev->driver,
628  "Unable to register v4l2 device.\n");
629  goto fail_clk_put;
630  }
631  v4l2_info(&vpbe_dev->v4l2_dev, "vpbe v4l2 device registered\n");
632 
633  err = bus_for_each_dev(&platform_bus_type, NULL, vpbe_dev,
634  platform_device_get);
635  if (err < 0)
636  return err;
637 
638  vpbe_dev->venc = venc_sub_dev_init(&vpbe_dev->v4l2_dev,
639  vpbe_dev->cfg->venc.module_name);
640  /* register venc sub device */
641  if (vpbe_dev->venc == NULL) {
642  v4l2_err(&vpbe_dev->v4l2_dev,
643  "vpbe unable to init venc sub device\n");
644  ret = -ENODEV;
645  goto fail_dev_unregister;
646  }
647  /* initialize osd device */
648  osd_device = vpbe_dev->osd_device;
649 
650  if (NULL != osd_device->ops.initialize) {
651  err = osd_device->ops.initialize(osd_device);
652  if (err) {
653  v4l2_err(&vpbe_dev->v4l2_dev,
654  "unable to initialize the OSD device");
655  err = -ENOMEM;
656  goto fail_dev_unregister;
657  }
658  }
659 
660  /*
661  * Register any external encoders that are configured. At index 0 we
662  * store venc sd index.
663  */
664  num_encoders = vpbe_dev->cfg->num_ext_encoders + 1;
665  vpbe_dev->encoders = kmalloc(
666  sizeof(struct v4l2_subdev *)*num_encoders,
667  GFP_KERNEL);
668  if (NULL == vpbe_dev->encoders) {
669  v4l2_err(&vpbe_dev->v4l2_dev,
670  "unable to allocate memory for encoders sub devices");
671  ret = -ENOMEM;
672  goto fail_dev_unregister;
673  }
674 
675  i2c_adap = i2c_get_adapter(vpbe_dev->cfg->i2c_adapter_id);
676  for (i = 0; i < (vpbe_dev->cfg->num_ext_encoders + 1); i++) {
677  if (i == 0) {
678  /* venc is at index 0 */
679  enc_subdev = &vpbe_dev->encoders[i];
680  *enc_subdev = vpbe_dev->venc;
681  continue;
682  }
683  enc_info = &vpbe_dev->cfg->ext_encoders[i];
684  if (enc_info->is_i2c) {
685  enc_subdev = &vpbe_dev->encoders[i];
686  *enc_subdev = v4l2_i2c_new_subdev_board(
687  &vpbe_dev->v4l2_dev, i2c_adap,
688  &enc_info->board_info, NULL);
689  if (*enc_subdev)
690  v4l2_info(&vpbe_dev->v4l2_dev,
691  "v4l2 sub device %s registered\n",
692  enc_info->module_name);
693  else {
694  v4l2_err(&vpbe_dev->v4l2_dev, "encoder %s"
695  " failed to register",
696  enc_info->module_name);
697  ret = -ENODEV;
698  goto fail_kfree_encoders;
699  }
700  } else
701  v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders"
702  " currently not supported");
703  }
704  /* Add amplifier subdevice for dm365 */
705  if ((strcmp(vpbe_dev->cfg->module_name, "dm365-vpbe-display") == 0) &&
706  vpbe_dev->cfg->amp != NULL) {
707  amp_info = vpbe_dev->cfg->amp;
708  if (amp_info->is_i2c) {
709  vpbe_dev->amp = v4l2_i2c_new_subdev_board(
710  &vpbe_dev->v4l2_dev, i2c_adap,
711  &amp_info->board_info, NULL);
712  if (!vpbe_dev->amp) {
713  v4l2_err(&vpbe_dev->v4l2_dev,
714  "amplifier %s failed to register",
715  amp_info->module_name);
716  ret = -ENODEV;
717  goto fail_kfree_encoders;
718  }
719  v4l2_info(&vpbe_dev->v4l2_dev,
720  "v4l2 sub device %s registered\n",
721  amp_info->module_name);
722  } else {
723  vpbe_dev->amp = NULL;
724  v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c amplifiers"
725  " currently not supported");
726  }
727  } else {
728  vpbe_dev->amp = NULL;
729  }
730 
731  /* set the current encoder and output to that of venc by default */
732  vpbe_dev->current_sd_index = 0;
733  vpbe_dev->current_out_index = 0;
734  output_index = 0;
735 
736  mutex_unlock(&vpbe_dev->lock);
737 
738  printk(KERN_NOTICE "Setting default output to %s\n", def_output);
739  ret = vpbe_set_default_output(vpbe_dev);
740  if (ret) {
741  v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default output %s",
742  def_output);
743  return ret;
744  }
745 
746  printk(KERN_NOTICE "Setting default mode to %s\n", def_mode);
747  ret = vpbe_set_default_mode(vpbe_dev);
748  if (ret) {
749  v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default mode %s",
750  def_mode);
751  return ret;
752  }
753  vpbe_dev->initialized = 1;
754  /* TBD handling of bootargs for default output and mode */
755  return 0;
756 
757 fail_kfree_encoders:
758  kfree(vpbe_dev->encoders);
759 fail_dev_unregister:
760  v4l2_device_unregister(&vpbe_dev->v4l2_dev);
761 fail_clk_put:
762  if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0)
763  clk_put(vpbe_dev->dac_clk);
764 fail_mutex_unlock:
765  mutex_unlock(&vpbe_dev->lock);
766  return ret;
767 }
768 
777 static void vpbe_deinitialize(struct device *dev, struct vpbe_device *vpbe_dev)
778 {
779  v4l2_device_unregister(&vpbe_dev->v4l2_dev);
780  if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0)
781  clk_put(vpbe_dev->dac_clk);
782 
783  kfree(vpbe_dev->amp);
784  kfree(vpbe_dev->encoders);
785  vpbe_dev->initialized = 0;
786  /* disable vpss clocks */
788 }
789 
790 static struct vpbe_device_ops vpbe_dev_ops = {
791  .g_cropcap = vpbe_g_cropcap,
792  .enum_outputs = vpbe_enum_outputs,
793  .set_output = vpbe_set_output,
794  .get_output = vpbe_get_output,
795  .s_dv_timings = vpbe_s_dv_timings,
796  .g_dv_timings = vpbe_g_dv_timings,
797  .enum_dv_timings = vpbe_enum_dv_timings,
798  .s_std = vpbe_s_std,
799  .g_std = vpbe_g_std,
800  .initialize = vpbe_initialize,
801  .deinitialize = vpbe_deinitialize,
802  .get_mode_info = vpbe_get_current_mode_info,
803  .set_mode = vpbe_set_mode,
804 };
805 
806 static __devinit int vpbe_probe(struct platform_device *pdev)
807 {
808  struct vpbe_device *vpbe_dev;
809  struct vpbe_config *cfg;
810  int ret = -EINVAL;
811 
812  if (pdev->dev.platform_data == NULL) {
813  v4l2_err(pdev->dev.driver, "No platform data\n");
814  return -ENODEV;
815  }
816  cfg = pdev->dev.platform_data;
817 
818  if (!cfg->module_name[0] ||
819  !cfg->osd.module_name[0] ||
820  !cfg->venc.module_name[0]) {
821  v4l2_err(pdev->dev.driver, "vpbe display module names not"
822  " defined\n");
823  return ret;
824  }
825 
826  vpbe_dev = kzalloc(sizeof(*vpbe_dev), GFP_KERNEL);
827  if (vpbe_dev == NULL) {
828  v4l2_err(pdev->dev.driver, "Unable to allocate memory"
829  " for vpbe_device\n");
830  return -ENOMEM;
831  }
832  vpbe_dev->cfg = cfg;
833  vpbe_dev->ops = vpbe_dev_ops;
834  vpbe_dev->pdev = &pdev->dev;
835 
836  if (cfg->outputs->num_modes > 0)
837  vpbe_dev->current_timings = vpbe_dev->cfg->outputs[0].modes[0];
838  else {
839  kfree(vpbe_dev);
840  return -ENODEV;
841  }
842 
843  /* set the driver data in platform device */
844  platform_set_drvdata(pdev, vpbe_dev);
845  mutex_init(&vpbe_dev->lock);
846 
847  return 0;
848 }
849 
850 static int vpbe_remove(struct platform_device *device)
851 {
852  struct vpbe_device *vpbe_dev = platform_get_drvdata(device);
853 
854  kfree(vpbe_dev);
855 
856  return 0;
857 }
858 
859 static struct platform_driver vpbe_driver = {
860  .driver = {
861  .name = "vpbe_controller",
862  .owner = THIS_MODULE,
863  },
864  .probe = vpbe_probe,
865  .remove = vpbe_remove,
866 };
867 
868 module_platform_driver(vpbe_driver);