aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/em28xx/em28xx-camera.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2013-08-28 09:28:28 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2013-10-31 02:36:48 -0400
commitfc5d0f8a8878319f6cb87045fd704360b2bb4e52 (patch)
treee0dbd0795a100088ad47f4df0f0c335e484f112a /drivers/media/usb/em28xx/em28xx-camera.c
parent774cc4c289152bfb77806ccae722a9ae2d29dd02 (diff)
[media] V4L2: em28xx: register a V4L2 clock source
Camera sensors usually require a master clock for data sampling. This patch registers such a clock source for em28xx cameras. This fixes the currently broken em28xx ov2640 camera support and can also be used by other camera sensors. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/usb/em28xx/em28xx-camera.c')
-rw-r--r--drivers/media/usb/em28xx/em28xx-camera.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c
index 73cc50afa5e1..2f451e40edaf 100644
--- a/drivers/media/usb/em28xx/em28xx-camera.c
+++ b/drivers/media/usb/em28xx/em28xx-camera.c
@@ -22,6 +22,7 @@
22#include <linux/i2c.h> 22#include <linux/i2c.h>
23#include <media/soc_camera.h> 23#include <media/soc_camera.h>
24#include <media/mt9v011.h> 24#include <media/mt9v011.h>
25#include <media/v4l2-clk.h>
25#include <media/v4l2-common.h> 26#include <media/v4l2-common.h>
26 27
27#include "em28xx.h" 28#include "em28xx.h"
@@ -325,13 +326,24 @@ int em28xx_detect_sensor(struct em28xx *dev)
325 326
326int em28xx_init_camera(struct em28xx *dev) 327int em28xx_init_camera(struct em28xx *dev)
327{ 328{
329 char clk_name[V4L2_SUBDEV_NAME_SIZE];
330 struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus];
331 struct i2c_adapter *adap = &dev->i2c_adap[dev->def_i2c_bus];
332 int ret = 0;
333
334 v4l2_clk_name_i2c(clk_name, sizeof(clk_name),
335 i2c_adapter_id(adap), client->addr);
336 dev->clk = v4l2_clk_register_fixed(clk_name, "mclk", -EINVAL);
337 if (IS_ERR(dev->clk))
338 return PTR_ERR(dev->clk);
339
328 switch (dev->em28xx_sensor) { 340 switch (dev->em28xx_sensor) {
329 case EM28XX_MT9V011: 341 case EM28XX_MT9V011:
330 { 342 {
331 struct mt9v011_platform_data pdata; 343 struct mt9v011_platform_data pdata;
332 struct i2c_board_info mt9v011_info = { 344 struct i2c_board_info mt9v011_info = {
333 .type = "mt9v011", 345 .type = "mt9v011",
334 .addr = dev->i2c_client[dev->def_i2c_bus].addr, 346 .addr = client->addr,
335 .platform_data = &pdata, 347 .platform_data = &pdata,
336 }; 348 };
337 349
@@ -352,10 +364,11 @@ int em28xx_init_camera(struct em28xx *dev)
352 dev->sensor_xtal = 4300000; 364 dev->sensor_xtal = 4300000;
353 pdata.xtal = dev->sensor_xtal; 365 pdata.xtal = dev->sensor_xtal;
354 if (NULL == 366 if (NULL ==
355 v4l2_i2c_new_subdev_board(&dev->v4l2_dev, 367 v4l2_i2c_new_subdev_board(&dev->v4l2_dev, adap,
356 &dev->i2c_adap[dev->def_i2c_bus], 368 &mt9v011_info, NULL)) {
357 &mt9v011_info, NULL)) 369 ret = -ENODEV;
358 return -ENODEV; 370 break;
371 }
359 /* probably means GRGB 16 bit bayer */ 372 /* probably means GRGB 16 bit bayer */
360 dev->vinmode = 0x0d; 373 dev->vinmode = 0x0d;
361 dev->vinctl = 0x00; 374 dev->vinctl = 0x00;
@@ -391,7 +404,7 @@ int em28xx_init_camera(struct em28xx *dev)
391 struct i2c_board_info ov2640_info = { 404 struct i2c_board_info ov2640_info = {
392 .type = "ov2640", 405 .type = "ov2640",
393 .flags = I2C_CLIENT_SCCB, 406 .flags = I2C_CLIENT_SCCB,
394 .addr = dev->i2c_client[dev->def_i2c_bus].addr, 407 .addr = client->addr,
395 .platform_data = &camlink, 408 .platform_data = &camlink,
396 }; 409 };
397 struct v4l2_mbus_framefmt fmt; 410 struct v4l2_mbus_framefmt fmt;
@@ -408,9 +421,12 @@ int em28xx_init_camera(struct em28xx *dev)
408 dev->sensor_yres = 480; 421 dev->sensor_yres = 480;
409 422
410 subdev = 423 subdev =
411 v4l2_i2c_new_subdev_board(&dev->v4l2_dev, 424 v4l2_i2c_new_subdev_board(&dev->v4l2_dev, adap,
412 &dev->i2c_adap[dev->def_i2c_bus],
413 &ov2640_info, NULL); 425 &ov2640_info, NULL);
426 if (NULL == subdev) {
427 ret = -ENODEV;
428 break;
429 }
414 430
415 fmt.code = V4L2_MBUS_FMT_YUYV8_2X8; 431 fmt.code = V4L2_MBUS_FMT_YUYV8_2X8;
416 fmt.width = 640; 432 fmt.width = 640;
@@ -427,8 +443,13 @@ int em28xx_init_camera(struct em28xx *dev)
427 } 443 }
428 case EM28XX_NOSENSOR: 444 case EM28XX_NOSENSOR:
429 default: 445 default:
430 return -EINVAL; 446 ret = -EINVAL;
431 } 447 }
432 448
433 return 0; 449 if (ret < 0) {
450 v4l2_clk_unregister_fixed(dev->clk);
451 dev->clk = NULL;
452 }
453
454 return ret;
434} 455}