diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-04 18:50:07 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-04 18:50:07 +0200 |
commit | 3c83e61e67256e0bb08c46cc2db43b58fd617251 (patch) | |
tree | 0233e1e04e6449c60b01ff5dea8bea85bcf22f08 /drivers/media/i2c/mt9p031.c | |
parent | Merge branch 'linux_next' of git://git.kernel.org/pub/scm/linux/kernel/git/mc... (diff) | |
parent | [media] em28xx-dvb: fix PCTV 461e tuner I2C binding (diff) | |
download | linux-3c83e61e67256e0bb08c46cc2db43b58fd617251.tar.xz linux-3c83e61e67256e0bb08c46cc2db43b58fd617251.zip |
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:
"The main set of series of patches for media subsystem, including:
- document RC sysfs class
- added an API to setup scancode to allow waking up systems using the
Remote Controller
- add API for SDR devices. Drivers are still on staging
- some API improvements for getting EDID data from media
inputs/outputs
- new DVB frontend driver for drx-j (ATSC)
- one driver (it913x/it9137) got removed, in favor of an improvement
on another driver (af9035)
- added a skeleton V4L2 PCI driver at documentation
- added a dual flash driver (lm3646)
- added a new IR driver (img-ir)
- added an IR scancode decoder for the Sharp protocol
- some improvements at the usbtv driver, to allow its core to be
reused.
- added a new SDR driver (rtl2832u_sdr)
- added a new tuner driver (msi001)
- several improvements at em28xx driver to fix PM support, device
removal and to split the V4L2 specific bits into a separate
sub-driver
- one driver got converted to videobuf2 (s2255drv)
- the e4000 tuner driver now follows an improved binding model
- some fixes at V4L2 compat32 code
- several fixes and enhancements at videobuf2 code
- some cleanups at V4L2 API documentation
- usual driver enhancements, new board additions and misc fixups"
[ NOTE! This merge effective drops commit 4329b93b283c ("of: Reduce
indentation in of_graph_get_next_endpoint").
The of_graph_get_next_endpoint() function was moved and renamed by
commit fd9fdb78a9bf ("[media] of: move graph helpers from
drivers/media/v4l2-core to drivers/of"). It was originally called
v4l2_of_get_next_endpoint() and lived in the file
drivers/media/v4l2-core/v4l2-of.c.
In that original location, it was then fixed to support empty port
nodes by commit b9db140c1e46 ("[media] v4l: of: Support empty port
nodes"), and that commit clashes badly with the dropped "Reduce
intendation" commit. I had to choose one or the other, and decided
that the "Support empty port nodes" commit was more important ]
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (426 commits)
[media] em28xx-dvb: fix PCTV 461e tuner I2C binding
Revert "[media] em28xx-dvb: fix PCTV 461e tuner I2C binding"
[media] em28xx: fix PCTV 290e LNA oops
[media] em28xx-dvb: fix PCTV 461e tuner I2C binding
[media] m88ds3103: fix bug on .set_tone()
[media] saa7134: fix WARN_ON during resume
[media] v4l2-dv-timings: add module name, description, license
[media] videodev2.h: add parenthesis around macro arguments
[media] saa6752hs: depends on CRC32
[media] si4713: fix Kconfig dependencies
[media] Sensoray 2255 uses videobuf2
[media] adv7180: free an interrupt on failure paths in init_device()
[media] e4000: make VIDEO_V4L2 dependency optional
[media] af9033: Don't export functions for the hardware filter
[media] af9035: use af9033 PID filters
[media] af9033: implement PID filter
[media] rtl2832_sdr: do not use dynamic stack allocation
[media] e4000: fix 32-bit build error
[media] em28xx-audio: make sure audio is unmuted on open()
[media] DocBook media: v4l2_format_sdr was renamed to v4l2_sdr_format
...
Diffstat (limited to 'drivers/media/i2c/mt9p031.c')
-rw-r--r-- | drivers/media/i2c/mt9p031.c | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index 192c4aad05d6..33daace81297 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -78,6 +78,9 @@ #define MT9P031_PLL_CONFIG_1 0x11 #define MT9P031_PLL_CONFIG_2 0x12 #define MT9P031_PIXEL_CLOCK_CONTROL 0x0a +#define MT9P031_PIXEL_CLOCK_INVERT (1 << 15) +#define MT9P031_PIXEL_CLOCK_SHIFT(n) ((n) << 8) +#define MT9P031_PIXEL_CLOCK_DIVIDE(n) ((n) << 0) #define MT9P031_FRAME_RESTART 0x0b #define MT9P031_SHUTTER_DELAY 0x0c #define MT9P031_RST 0x0d @@ -130,6 +133,8 @@ struct mt9p031 { enum mt9p031_model model; struct aptina_pll pll; + unsigned int clk_div; + bool use_pll; int reset; struct v4l2_ctrl_handler ctrls; @@ -198,6 +203,11 @@ static int mt9p031_reset(struct mt9p031 *mt9p031) if (ret < 0) return ret; + ret = mt9p031_write(client, MT9P031_PIXEL_CLOCK_CONTROL, + MT9P031_PIXEL_CLOCK_DIVIDE(mt9p031->clk_div)); + if (ret < 0) + return ret; + return mt9p031_set_output_control(mt9p031, MT9P031_OUTPUT_CONTROL_CEN, 0); } @@ -222,15 +232,34 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031) struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); struct mt9p031_platform_data *pdata = mt9p031->pdata; + int ret; mt9p031->clk = devm_clk_get(&client->dev, NULL); if (IS_ERR(mt9p031->clk)) return PTR_ERR(mt9p031->clk); - clk_set_rate(mt9p031->clk, pdata->ext_freq); + ret = clk_set_rate(mt9p031->clk, pdata->ext_freq); + if (ret < 0) + return ret; + + /* If the external clock frequency is out of bounds for the PLL use the + * pixel clock divider only and disable the PLL. + */ + if (pdata->ext_freq > limits.ext_clock_max) { + unsigned int div; + + div = DIV_ROUND_UP(pdata->ext_freq, pdata->target_freq); + div = roundup_pow_of_two(div) / 2; + + mt9p031->clk_div = max_t(unsigned int, div, 64); + mt9p031->use_pll = false; + + return 0; + } mt9p031->pll.ext_clock = pdata->ext_freq; mt9p031->pll.pix_clock = pdata->target_freq; + mt9p031->use_pll = true; return aptina_pll_calculate(&client->dev, &limits, &mt9p031->pll); } @@ -240,6 +269,9 @@ static int mt9p031_pll_enable(struct mt9p031 *mt9p031) struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); int ret; + if (!mt9p031->use_pll) + return 0; + ret = mt9p031_write(client, MT9P031_PLL_CONTROL, MT9P031_PLL_CONTROL_PWRON); if (ret < 0) @@ -265,6 +297,9 @@ static inline int mt9p031_pll_disable(struct mt9p031 *mt9p031) { struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); + if (!mt9p031->use_pll) + return 0; + return mt9p031_write(client, MT9P031_PLL_CONTROL, MT9P031_PLL_CONTROL_PWROFF); } @@ -285,9 +320,15 @@ static int mt9p031_power_on(struct mt9p031 *mt9p031) if (ret < 0) return ret; - /* Emable clock */ - if (mt9p031->clk) - clk_prepare_enable(mt9p031->clk); + /* Enable clock */ + if (mt9p031->clk) { + ret = clk_prepare_enable(mt9p031->clk); + if (ret) { + regulator_bulk_disable(ARRAY_SIZE(mt9p031->regulators), + mt9p031->regulators); + return ret; + } + } /* Now RESET_BAR must be high */ if (gpio_is_valid(mt9p031->reset)) { |