diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-23 14:39:09 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-23 14:39:09 -0700 |
commit | e317234975cb7463b8ca21a93bb6862d9dcf113f (patch) | |
tree | 4446fa3a21364f3cba23a22aa2a94027f169d8df /drivers/media/video/s5p-tv/hdmi_drv.c | |
parent | f37ab0fba271e43edab0e3ae9fe644fcda455402 (diff) | |
parent | 7483d45f0aee3afc0646d185cabd4af9f6cab58c (diff) |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- V4L2 API additions to better support JPEG compression control
- media API additions to properly support MPEG decoders
- V4L2 API additions for image crop/scaling
- a few other V4L2 API DocBook fixes/improvements
- two new DVB frontend drivers: m88rs2000 and rtl2830
- two new DVB drivers: az6007 and rtl28xxu
- a framework for ISA drivers, that removed lots of common code found
at the ISA radio drivers
- a new FM transmitter driver (radio-keene)
- a GPIO-based IR receiver driver
- a new sensor driver: mt9m032
- some new video drivers: adv7183, blackfin, mx2_emmaprp, sii9234_drv,
vs6624
- several new board additions, driver fixes, improvements and cleanups.
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (295 commits)
[media] update CARDLIST.em28xx
[media] partially reverts changeset fa5527c
[media] stb0899: fix the limits for signal strength values
[media] em28xx: support for 2304:0242 PCTV QuatroStick (510e)
[media] em28xx: support for 2013:0251 PCTV QuatroStick nano (520e)
[media] -EINVAL -> -ENOTTY
[media] gspca - sn9c20x: Cleanup source
[media] gspca - sn9c20x: Simplify register write for capture start/stop
[media] gspca - sn9c20x: Add automatic JPEG compression mechanism
[media] gspca - sn9c20x: Greater delay in case of sensor no response
[media] gspca - sn9c20x: Optimize the code of write sequences
[media] gspca - sn9c20x: Add the JPEG compression quality control
[media] gspca - sn9c20x: Add a delay after Omnivision sensor reset
[media] gspca - sn9c20x: Propagate USB errors to higher level
[media] gspca - sn9c20x: Use the new video control mechanism
[media] gspca - sn9c20x: Fix loss of frame start
[media] gspca - zc3xx: Lack of register 08 value for sensor cs2102k
[media] gspca - ov534_9: Add brightness to OmniVision 5621 sensor
[media] gspca - zc3xx: Add V4L2_CID_JPEG_COMPRESSION_QUALITY control support
[media] pvrusb2: fix 7MHz & 8MHz DVB-T tuner support for HVR1900 rev D1F5
...
Diffstat (limited to 'drivers/media/video/s5p-tv/hdmi_drv.c')
-rw-r--r-- | drivers/media/video/s5p-tv/hdmi_drv.c | 120 |
1 files changed, 72 insertions, 48 deletions
diff --git a/drivers/media/video/s5p-tv/hdmi_drv.c b/drivers/media/video/s5p-tv/hdmi_drv.c index 8b41a0410ab..4865d25a0e5 100644 --- a/drivers/media/video/s5p-tv/hdmi_drv.c +++ b/drivers/media/video/s5p-tv/hdmi_drv.c @@ -30,6 +30,7 @@ #include <linux/clk.h> #include <linux/regulator/consumer.h> +#include <media/s5p_hdmi.h> #include <media/v4l2-common.h> #include <media/v4l2-dev.h> #include <media/v4l2-device.h> @@ -66,6 +67,8 @@ struct hdmi_device { struct v4l2_device v4l2_dev; /** subdev of HDMIPHY interface */ struct v4l2_subdev *phy_sd; + /** subdev of MHL interface */ + struct v4l2_subdev *mhl_sd; /** configuration of current graphic mode */ const struct hdmi_preset_conf *cur_conf; /** current preset */ @@ -74,10 +77,6 @@ struct hdmi_device { struct hdmi_resources res; }; -struct hdmi_driver_data { - int hdmiphy_bus; -}; - struct hdmi_tg_regs { u8 cmd; u8 h_fsz_l; @@ -129,23 +128,11 @@ struct hdmi_preset_conf { struct v4l2_mbus_framefmt mbus_fmt; }; -/* I2C module and id for HDMIPHY */ -static struct i2c_board_info hdmiphy_info = { - I2C_BOARD_INFO("hdmiphy", 0x38), -}; - -static struct hdmi_driver_data hdmi_driver_data[] = { - { .hdmiphy_bus = 3 }, - { .hdmiphy_bus = 8 }, -}; - static struct platform_device_id hdmi_driver_types[] = { { .name = "s5pv210-hdmi", - .driver_data = (unsigned long)&hdmi_driver_data[0], }, { .name = "exynos4-hdmi", - .driver_data = (unsigned long)&hdmi_driver_data[1], }, { /* end node */ } @@ -587,7 +574,15 @@ static int hdmi_streamon(struct hdmi_device *hdev) if (tries == 0) { dev_err(dev, "hdmiphy's pll could not reach steady state.\n"); v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); - hdmi_dumpregs(hdev, "s_stream"); + hdmi_dumpregs(hdev, "hdmiphy - s_stream"); + return -EIO; + } + + /* starting MHL */ + ret = v4l2_subdev_call(hdev->mhl_sd, video, s_stream, 1); + if (hdev->mhl_sd && ret) { + v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); + hdmi_dumpregs(hdev, "mhl - s_stream"); return -EIO; } @@ -618,6 +613,7 @@ static int hdmi_streamoff(struct hdmi_device *hdev) clk_set_parent(res->sclk_hdmi, res->sclk_pixel); clk_enable(res->sclk_hdmi); + v4l2_subdev_call(hdev->mhl_sd, video, s_stream, 0); v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); hdmi_dumpregs(hdev, "streamoff"); @@ -739,6 +735,7 @@ static int hdmi_runtime_suspend(struct device *dev) struct hdmi_device *hdev = sd_to_hdmi_dev(sd); dev_dbg(dev, "%s\n", __func__); + v4l2_subdev_call(hdev->mhl_sd, core, s_power, 0); hdmi_resource_poweroff(&hdev->res); return 0; } @@ -757,6 +754,11 @@ static int hdmi_runtime_resume(struct device *dev) if (ret) goto fail; + /* starting MHL */ + ret = v4l2_subdev_call(hdev->mhl_sd, core, s_power, 1); + if (hdev->mhl_sd && ret) + goto fail; + dev_dbg(dev, "poweron succeed\n"); return 0; @@ -867,15 +869,21 @@ static int __devinit hdmi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; - struct i2c_adapter *phy_adapter; + struct i2c_adapter *adapter; struct v4l2_subdev *sd; struct hdmi_device *hdmi_dev = NULL; - struct hdmi_driver_data *drv_data; + struct s5p_hdmi_platform_data *pdata = dev->platform_data; int ret; dev_dbg(dev, "probe start\n"); - hdmi_dev = kzalloc(sizeof(*hdmi_dev), GFP_KERNEL); + if (!pdata) { + dev_err(dev, "platform data is missing\n"); + ret = -ENODEV; + goto fail; + } + + hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(*hdmi_dev), GFP_KERNEL); if (!hdmi_dev) { dev_err(dev, "out of memory\n"); ret = -ENOMEM; @@ -886,7 +894,7 @@ static int __devinit hdmi_probe(struct platform_device *pdev) ret = hdmi_resources_init(hdmi_dev); if (ret) - goto fail_hdev; + goto fail; /* mapping HDMI registers */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -896,24 +904,26 @@ static int __devinit hdmi_probe(struct platform_device *pdev) goto fail_init; } - hdmi_dev->regs = ioremap(res->start, resource_size(res)); + hdmi_dev->regs = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); if (hdmi_dev->regs == NULL) { dev_err(dev, "register mapping failed.\n"); ret = -ENXIO; - goto fail_hdev; + goto fail_init; } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res == NULL) { dev_err(dev, "get interrupt resource failed.\n"); ret = -ENXIO; - goto fail_regs; + goto fail_init; } - ret = request_irq(res->start, hdmi_irq_handler, 0, "hdmi", hdmi_dev); + ret = devm_request_irq(&pdev->dev, res->start, hdmi_irq_handler, 0, + "hdmi", hdmi_dev); if (ret) { dev_err(dev, "request interrupt failed.\n"); - goto fail_regs; + goto fail_init; } hdmi_dev->irq = res->start; @@ -924,28 +934,54 @@ static int __devinit hdmi_probe(struct platform_device *pdev) ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev); if (ret) { dev_err(dev, "could not register v4l2 device.\n"); - goto fail_irq; + goto fail_init; } - drv_data = (struct hdmi_driver_data *) - platform_get_device_id(pdev)->driver_data; - phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus); - if (phy_adapter == NULL) { - dev_err(dev, "adapter request failed\n"); + /* testing if hdmiphy info is present */ + if (!pdata->hdmiphy_info) { + dev_err(dev, "hdmiphy info is missing in platform data\n"); + ret = -ENXIO; + goto fail_vdev; + } + + adapter = i2c_get_adapter(pdata->hdmiphy_bus); + if (adapter == NULL) { + dev_err(dev, "hdmiphy adapter request failed\n"); ret = -ENXIO; goto fail_vdev; } hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev, - phy_adapter, &hdmiphy_info, NULL); + adapter, pdata->hdmiphy_info, NULL); /* on failure or not adapter is no longer useful */ - i2c_put_adapter(phy_adapter); + i2c_put_adapter(adapter); if (hdmi_dev->phy_sd == NULL) { dev_err(dev, "missing subdev for hdmiphy\n"); ret = -ENODEV; goto fail_vdev; } + /* initialization of MHL interface if present */ + if (pdata->mhl_info) { + adapter = i2c_get_adapter(pdata->mhl_bus); + if (adapter == NULL) { + dev_err(dev, "MHL adapter request failed\n"); + ret = -ENXIO; + goto fail_vdev; + } + + hdmi_dev->mhl_sd = v4l2_i2c_new_subdev_board( + &hdmi_dev->v4l2_dev, adapter, + pdata->mhl_info, NULL); + /* on failure or not adapter is no longer useful */ + i2c_put_adapter(adapter); + if (hdmi_dev->mhl_sd == NULL) { + dev_err(dev, "missing subdev for MHL\n"); + ret = -ENODEV; + goto fail_vdev; + } + } + clk_enable(hdmi_dev->res.hdmi); pm_runtime_enable(dev); @@ -962,25 +998,16 @@ static int __devinit hdmi_probe(struct platform_device *pdev) /* storing subdev for call that have only access to struct device */ dev_set_drvdata(dev, sd); - dev_info(dev, "probe sucessful\n"); + dev_info(dev, "probe successful\n"); return 0; fail_vdev: v4l2_device_unregister(&hdmi_dev->v4l2_dev); -fail_irq: - free_irq(hdmi_dev->irq, hdmi_dev); - -fail_regs: - iounmap(hdmi_dev->regs); - fail_init: hdmi_resources_cleanup(hdmi_dev); -fail_hdev: - kfree(hdmi_dev); - fail: dev_err(dev, "probe failed\n"); return ret; @@ -996,11 +1023,8 @@ static int __devexit hdmi_remove(struct platform_device *pdev) clk_disable(hdmi_dev->res.hdmi); v4l2_device_unregister(&hdmi_dev->v4l2_dev); disable_irq(hdmi_dev->irq); - free_irq(hdmi_dev->irq, hdmi_dev); - iounmap(hdmi_dev->regs); hdmi_resources_cleanup(hdmi_dev); - kfree(hdmi_dev); - dev_info(dev, "remove sucessful\n"); + dev_info(dev, "remove successful\n"); return 0; } |