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 4329b93b28 ("of: Reduce
  indentation in of_graph_get_next_endpoint").

  The of_graph_get_next_endpoint() function was moved and renamed by
  commit fd9fdb78a9 ("[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 b9db140c1e ("[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
  ...
This commit is contained in:
Linus Torvalds
2014-04-04 09:50:07 -07:00
384 fájl változott, egészen pontosan 44036 új sor hozzáadva és 7945 régi sor törölve

Fájl megtekintése

@@ -196,7 +196,7 @@ config VIDEO_ADV7183
config VIDEO_ADV7604
tristate "Analog Devices ADV7604 decoder"
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
---help---
Support for the Analog Devices ADV7604 video decoder.
@@ -208,7 +208,7 @@ config VIDEO_ADV7604
config VIDEO_ADV7842
tristate "Analog Devices ADV7842 decoder"
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
---help---
Support for the Analog Devices ADV7842 video decoder.
@@ -431,7 +431,7 @@ config VIDEO_ADV7393
config VIDEO_ADV7511
tristate "Analog Devices ADV7511 encoder"
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
---help---
Support for the Analog Devices ADV7511 video encoder.
@@ -629,6 +629,15 @@ config VIDEO_LM3560
This is a driver for the lm3560 dual flash controllers. It controls
flash, torch LEDs.
config VIDEO_LM3646
tristate "LM3646 dual flash driver support"
depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
depends on MEDIA_CAMERA_SUPPORT
select REGMAP_I2C
---help---
This is a driver for the lm3646 dual flash controllers. It controls
flash, torch LEDs.
comment "Video improvement chips"
config VIDEO_UPD64031A
@@ -659,6 +668,7 @@ comment "Audio/Video compression chips"
config VIDEO_SAA6752HS
tristate "Philips SAA6752HS MPEG-2 Audio/Video Encoder"
depends on VIDEO_V4L2 && I2C
select CRC32
---help---
Support for the Philips SAA6752HS MPEG-2 video and MPEG-audio/AC-3
audio encoder with multiplexer.

Fájl megtekintése

@@ -72,6 +72,7 @@ obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/
obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o
obj-$(CONFIG_VIDEO_AS3645A) += as3645a.o
obj-$(CONFIG_VIDEO_LM3560) += lm3560.o
obj-$(CONFIG_VIDEO_LM3646) += lm3646.o
obj-$(CONFIG_VIDEO_SMIAPP_PLL) += smiapp-pll.o
obj-$(CONFIG_VIDEO_AK881X) += ak881x.o
obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o

Fájl megtekintése

@@ -573,7 +573,7 @@ static const struct v4l2_subdev_core_ops ad9389b_core_ops = {
/* ------------------------------ PAD OPS ------------------------------ */
static int ad9389b_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
static int ad9389b_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
{
struct ad9389b_state *state = get_ad9389b_state(sd);

Fájl megtekintése

@@ -123,11 +123,11 @@
struct adv7180_state {
struct v4l2_ctrl_handler ctrl_hdl;
struct v4l2_subdev sd;
struct work_struct work;
struct mutex mutex; /* mutual excl. when accessing chip */
int irq;
v4l2_std_id curr_norm;
bool autodetect;
bool powered;
u8 input;
};
#define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \
@@ -312,6 +312,37 @@ out:
return ret;
}
static int adv7180_set_power(struct adv7180_state *state,
struct i2c_client *client, bool on)
{
u8 val;
if (on)
val = ADV7180_PWR_MAN_ON;
else
val = ADV7180_PWR_MAN_OFF;
return i2c_smbus_write_byte_data(client, ADV7180_PWR_MAN_REG, val);
}
static int adv7180_s_power(struct v4l2_subdev *sd, int on)
{
struct adv7180_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
int ret;
ret = mutex_lock_interruptible(&state->mutex);
if (ret)
return ret;
ret = adv7180_set_power(state, client, on);
if (ret == 0)
state->powered = on;
mutex_unlock(&state->mutex);
return ret;
}
static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct v4l2_subdev *sd = to_adv7180_sd(ctrl);
@@ -442,6 +473,7 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = {
static const struct v4l2_subdev_core_ops adv7180_core_ops = {
.s_std = adv7180_s_std,
.s_power = adv7180_s_power,
};
static const struct v4l2_subdev_ops adv7180_ops = {
@@ -449,10 +481,9 @@ static const struct v4l2_subdev_ops adv7180_ops = {
.video = &adv7180_video_ops,
};
static void adv7180_work(struct work_struct *work)
static irqreturn_t adv7180_irq(int irq, void *devid)
{
struct adv7180_state *state = container_of(work, struct adv7180_state,
work);
struct adv7180_state *state = devid;
struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
u8 isr3;
@@ -468,17 +499,6 @@ static void adv7180_work(struct work_struct *work)
__adv7180_status(client, NULL, &state->curr_norm);
mutex_unlock(&state->mutex);
enable_irq(state->irq);
}
static irqreturn_t adv7180_irq(int irq, void *devid)
{
struct adv7180_state *state = devid;
schedule_work(&state->work);
disable_irq_nosync(state->irq);
return IRQ_HANDLED;
}
@@ -533,48 +553,52 @@ static int init_device(struct i2c_client *client, struct adv7180_state *state)
/* register for interrupts */
if (state->irq > 0) {
ret = request_irq(state->irq, adv7180_irq, 0, KBUILD_MODNAME,
state);
ret = request_threaded_irq(state->irq, NULL, adv7180_irq,
IRQF_ONESHOT, KBUILD_MODNAME, state);
if (ret)
return ret;
ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG,
ADV7180_ADI_CTRL_IRQ_SPACE);
if (ret < 0)
return ret;
goto err;
/* config the Interrupt pin to be active low */
ret = i2c_smbus_write_byte_data(client, ADV7180_ICONF1_ADI,
ADV7180_ICONF1_ACTIVE_LOW |
ADV7180_ICONF1_PSYNC_ONLY);
if (ret < 0)
return ret;
goto err;
ret = i2c_smbus_write_byte_data(client, ADV7180_IMR1_ADI, 0);
if (ret < 0)
return ret;
goto err;
ret = i2c_smbus_write_byte_data(client, ADV7180_IMR2_ADI, 0);
if (ret < 0)
return ret;
goto err;
/* enable AD change interrupts interrupts */
ret = i2c_smbus_write_byte_data(client, ADV7180_IMR3_ADI,
ADV7180_IRQ3_AD_CHANGE);
if (ret < 0)
return ret;
goto err;
ret = i2c_smbus_write_byte_data(client, ADV7180_IMR4_ADI, 0);
if (ret < 0)
return ret;
goto err;
ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG,
0);
if (ret < 0)
return ret;
goto err;
}
return 0;
err:
free_irq(state->irq, state);
return ret;
}
static int adv7180_probe(struct i2c_client *client,
@@ -598,9 +622,9 @@ static int adv7180_probe(struct i2c_client *client,
}
state->irq = client->irq;
INIT_WORK(&state->work, adv7180_work);
mutex_init(&state->mutex);
state->autodetect = true;
state->powered = true;
state->input = 0;
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &adv7180_ops);
@@ -611,15 +635,21 @@ static int adv7180_probe(struct i2c_client *client,
ret = init_device(client, state);
if (ret)
goto err_free_ctrl;
ret = v4l2_async_register_subdev(sd);
if (ret)
goto err_free_irq;
return 0;
err_free_irq:
if (state->irq > 0)
free_irq(client->irq, state);
err_free_ctrl:
adv7180_exit_controls(state);
err_unreg_subdev:
mutex_destroy(&state->mutex);
v4l2_device_unregister_subdev(sd);
err:
printk(KERN_ERR KBUILD_MODNAME ": Failed to probe: %d\n", ret);
return ret;
}
@@ -628,20 +658,14 @@ static int adv7180_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct adv7180_state *state = to_state(sd);
if (state->irq > 0) {
free_irq(client->irq, state);
if (cancel_work_sync(&state->work)) {
/*
* Work was pending, therefore we need to enable
* IRQ here to balance the disable_irq() done in the
* interrupt handler.
*/
enable_irq(state->irq);
}
}
v4l2_async_unregister_subdev(sd);
if (state->irq > 0)
free_irq(client->irq, state);
mutex_destroy(&state->mutex);
v4l2_device_unregister_subdev(sd);
adv7180_exit_controls(state);
mutex_destroy(&state->mutex);
return 0;
}
@@ -654,13 +678,10 @@ static const struct i2c_device_id adv7180_id[] = {
static int adv7180_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
int ret;
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct adv7180_state *state = to_state(sd);
ret = i2c_smbus_write_byte_data(client, ADV7180_PWR_MAN_REG,
ADV7180_PWR_MAN_OFF);
if (ret < 0)
return ret;
return 0;
return adv7180_set_power(state, client, false);
}
static int adv7180_resume(struct device *dev)
@@ -670,10 +691,11 @@ static int adv7180_resume(struct device *dev)
struct adv7180_state *state = to_state(sd);
int ret;
ret = i2c_smbus_write_byte_data(client, ADV7180_PWR_MAN_REG,
ADV7180_PWR_MAN_ON);
if (ret < 0)
return ret;
if (state->powered) {
ret = adv7180_set_power(state, client, true);
if (ret)
return ret;
}
ret = init_device(client, state);
if (ret < 0)
return ret;

Fájl megtekintése

@@ -597,7 +597,7 @@ static int adv7511_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
return 0;
}
static int adv7511_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
static int adv7511_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
{
struct adv7511_state *state = get_adv7511_state(sd);

Fájl megtekintése

@@ -1658,7 +1658,7 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
return 0;
}
static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
{
struct adv7604_state *state = to_state(sd);
u8 *data = NULL;
@@ -1728,7 +1728,7 @@ static int get_edid_spa_location(const u8 *edid)
return -1;
}
static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
{
struct adv7604_state *state = to_state(sd);
int spa_loc;

Fájl megtekintése

@@ -546,6 +546,14 @@ static void main_reset(struct v4l2_subdev *sd)
/* ----------------------------------------------------------------------- */
static inline bool is_analog_input(struct v4l2_subdev *sd)
{
struct adv7842_state *state = to_state(sd);
return ((state->mode == ADV7842_MODE_RGB) ||
(state->mode == ADV7842_MODE_COMP));
}
static inline bool is_digital_input(struct v4l2_subdev *sd)
{
struct adv7842_state *state = to_state(sd);
@@ -1027,12 +1035,72 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
cp_write(sd, 0xac, (height & 0x0f) << 4);
}
static void adv7842_set_offset(struct v4l2_subdev *sd, bool auto_offset, u16 offset_a, u16 offset_b, u16 offset_c)
{
struct adv7842_state *state = to_state(sd);
u8 offset_buf[4];
if (auto_offset) {
offset_a = 0x3ff;
offset_b = 0x3ff;
offset_c = 0x3ff;
}
v4l2_dbg(2, debug, sd, "%s: %s offset: a = 0x%x, b = 0x%x, c = 0x%x\n",
__func__, auto_offset ? "Auto" : "Manual",
offset_a, offset_b, offset_c);
offset_buf[0]= (cp_read(sd, 0x77) & 0xc0) | ((offset_a & 0x3f0) >> 4);
offset_buf[1] = ((offset_a & 0x00f) << 4) | ((offset_b & 0x3c0) >> 6);
offset_buf[2] = ((offset_b & 0x03f) << 2) | ((offset_c & 0x300) >> 8);
offset_buf[3] = offset_c & 0x0ff;
/* Registers must be written in this order with no i2c access in between */
if (adv_smbus_write_i2c_block_data(state->i2c_cp, 0x77, 4, offset_buf))
v4l2_err(sd, "%s: i2c error writing to CP reg 0x77, 0x78, 0x79, 0x7a\n", __func__);
}
static void adv7842_set_gain(struct v4l2_subdev *sd, bool auto_gain, u16 gain_a, u16 gain_b, u16 gain_c)
{
struct adv7842_state *state = to_state(sd);
u8 gain_buf[4];
u8 gain_man = 1;
u8 agc_mode_man = 1;
if (auto_gain) {
gain_man = 0;
agc_mode_man = 0;
gain_a = 0x100;
gain_b = 0x100;
gain_c = 0x100;
}
v4l2_dbg(2, debug, sd, "%s: %s gain: a = 0x%x, b = 0x%x, c = 0x%x\n",
__func__, auto_gain ? "Auto" : "Manual",
gain_a, gain_b, gain_c);
gain_buf[0] = ((gain_man << 7) | (agc_mode_man << 6) | ((gain_a & 0x3f0) >> 4));
gain_buf[1] = (((gain_a & 0x00f) << 4) | ((gain_b & 0x3c0) >> 6));
gain_buf[2] = (((gain_b & 0x03f) << 2) | ((gain_c & 0x300) >> 8));
gain_buf[3] = ((gain_c & 0x0ff));
/* Registers must be written in this order with no i2c access in between */
if (adv_smbus_write_i2c_block_data(state->i2c_cp, 0x73, 4, gain_buf))
v4l2_err(sd, "%s: i2c error writing to CP reg 0x73, 0x74, 0x75, 0x76\n", __func__);
}
static void set_rgb_quantization_range(struct v4l2_subdev *sd)
{
struct adv7842_state *state = to_state(sd);
bool rgb_output = io_read(sd, 0x02) & 0x02;
bool hdmi_signal = hdmi_read(sd, 0x05) & 0x80;
v4l2_dbg(2, debug, sd, "%s: rgb_quantization_range = %d\n",
__func__, state->rgb_quantization_range);
v4l2_dbg(2, debug, sd, "%s: RGB quantization range: %d, RGB out: %d, HDMI: %d\n",
__func__, state->rgb_quantization_range,
rgb_output, hdmi_signal);
adv7842_set_gain(sd, true, 0x0, 0x0, 0x0);
adv7842_set_offset(sd, true, 0x0, 0x0, 0x0);
switch (state->rgb_quantization_range) {
case V4L2_DV_RGB_RANGE_AUTO:
@@ -1050,7 +1118,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
break;
}
if (hdmi_read(sd, 0x05) & 0x80) {
if (hdmi_signal) {
/* Receiving HDMI signal
* Set automode */
io_write_and_or(sd, 0x02, 0x0f, 0xf0);
@@ -1066,24 +1134,45 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
} else {
/* RGB full range (0-255) */
io_write_and_or(sd, 0x02, 0x0f, 0x10);
if (is_digital_input(sd) && rgb_output) {
adv7842_set_offset(sd, false, 0x40, 0x40, 0x40);
} else {
adv7842_set_gain(sd, false, 0xe0, 0xe0, 0xe0);
adv7842_set_offset(sd, false, 0x70, 0x70, 0x70);
}
}
break;
case V4L2_DV_RGB_RANGE_LIMITED:
if (state->mode == ADV7842_MODE_COMP) {
/* YCrCb limited range (16-235) */
io_write_and_or(sd, 0x02, 0x0f, 0x20);
} else {
/* RGB limited range (16-235) */
io_write_and_or(sd, 0x02, 0x0f, 0x00);
break;
}
/* RGB limited range (16-235) */
io_write_and_or(sd, 0x02, 0x0f, 0x00);
break;
case V4L2_DV_RGB_RANGE_FULL:
if (state->mode == ADV7842_MODE_COMP) {
/* YCrCb full range (0-255) */
io_write_and_or(sd, 0x02, 0x0f, 0x60);
break;
}
/* RGB full range (0-255) */
io_write_and_or(sd, 0x02, 0x0f, 0x10);
if (is_analog_input(sd) || hdmi_signal)
break;
/* Adjust gain/offset for DVI-D signals only */
if (rgb_output) {
adv7842_set_offset(sd, false, 0x40, 0x40, 0x40);
} else {
/* RGB full range (0-255) */
io_write_and_or(sd, 0x02, 0x0f, 0x10);
adv7842_set_gain(sd, false, 0xe0, 0xe0, 0xe0);
adv7842_set_offset(sd, false, 0x70, 0x70, 0x70);
}
break;
}
@@ -1360,12 +1449,11 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd,
bt->width = (hdmi_read(sd, 0x07) & 0x0f) * 256 + hdmi_read(sd, 0x08);
bt->height = (hdmi_read(sd, 0x09) & 0x0f) * 256 + hdmi_read(sd, 0x0a);
freq = (hdmi_read(sd, 0x06) * 1000000) +
((hdmi_read(sd, 0x3b) & 0x30) >> 4) * 250000;
freq = ((hdmi_read(sd, 0x51) << 1) + (hdmi_read(sd, 0x52) >> 7)) * 1000000;
freq += ((hdmi_read(sd, 0x52) & 0x7f) * 7813);
if (is_hdmi(sd)) {
/* adjust for deep color mode */
freq = freq * 8 / (((hdmi_read(sd, 0x0b) & 0xc0) >> 5) + 8);
freq = freq * 8 / (((hdmi_read(sd, 0x0b) & 0xc0) >> 6) * 2 + 8);
}
bt->pixelclock = freq;
bt->hfrontporch = (hdmi_read(sd, 0x20) & 0x03) * 256 +
@@ -1717,8 +1805,8 @@ static void select_input(struct v4l2_subdev *sd,
* (rev. 2.5, June 2010)" p. 17. */
afe_write(sd, 0x12, 0xfb); /* ADC noise shaping filter controls */
afe_write(sd, 0x0c, 0x0d); /* CP core gain controls */
cp_write(sd, 0x3e, 0x80); /* CP core pre-gain control,
enable color control */
cp_write(sd, 0x3e, 0x00); /* CP core pre-gain control */
/* CP coast control */
cp_write(sd, 0xc3, 0x33); /* Component mode */
@@ -1926,7 +2014,7 @@ static int adv7842_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
return 0;
}
static int adv7842_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
static int adv7842_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
{
struct adv7842_state *state = to_state(sd);
u8 *data = NULL;
@@ -1966,7 +2054,7 @@ static int adv7842_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
return 0;
}
static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *e)
static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *e)
{
struct adv7842_state *state = to_state(sd);
int err = 0;
@@ -2103,7 +2191,8 @@ static void print_avi_infoframe(struct v4l2_subdev *sd)
{
int i;
uint8_t buf[14];
uint8_t avi_inf_len;
u8 avi_len;
u8 avi_ver;
struct avi_info_frame avi;
if (!(hdmi_read(sd, 0x05) & 0x80)) {
@@ -2116,18 +2205,20 @@ static void print_avi_infoframe(struct v4l2_subdev *sd)
}
if (io_read(sd, 0x88) & 0x10) {
/* Note: the ADV7842 calculated incorrect checksums for InfoFrames
with a length of 14 or 15. See the ADV7842 Register Settings
Recommendations document for more details. */
v4l2_info(sd, "AVI infoframe checksum error\n");
return;
v4l2_info(sd, "AVI infoframe checksum error has occurred earlier\n");
io_write(sd, 0x8a, 0x10); /* clear AVI_INF_CKS_ERR_RAW */
if (io_read(sd, 0x88) & 0x10) {
v4l2_info(sd, "AVI infoframe checksum error still present\n");
io_write(sd, 0x8a, 0x10); /* clear AVI_INF_CKS_ERR_RAW */
}
}
avi_inf_len = infoframe_read(sd, 0xe2);
avi_len = infoframe_read(sd, 0xe2);
avi_ver = infoframe_read(sd, 0xe1);
v4l2_info(sd, "AVI infoframe version %d (%d byte)\n",
infoframe_read(sd, 0xe1), avi_inf_len);
avi_ver, avi_len);
if (infoframe_read(sd, 0xe1) != 0x02)
if (avi_ver != 0x02)
return;
for (i = 0; i < 14; i++)
@@ -2602,9 +2693,15 @@ static int adv7842_core_init(struct v4l2_subdev *sd)
/* disable I2C access to internal EDID ram from HDMI DDC ports */
rep_write_and_or(sd, 0x77, 0xf3, 0x00);
hdmi_write(sd, 0x69, 0xa3); /* HPA manual */
/* HPA disable on port A and B */
io_write_and_or(sd, 0x20, 0xcf, 0x00);
if (pdata->hpa_auto) {
/* HPA auto, HPA 0.5s after Edid set and Cable detect */
hdmi_write(sd, 0x69, 0x5c);
} else {
/* HPA manual */
hdmi_write(sd, 0x69, 0xa3);
/* HPA disable on port A and B */
io_write_and_or(sd, 0x20, 0xcf, 0x00);
}
/* LLC */
io_write(sd, 0x19, 0x80 | pdata->llc_dll_phase);

Fájl megtekintése

@@ -431,8 +431,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
* Initialize the other fields of rc_dev
*/
rc->map_name = ir->ir_codes;
rc->allowed_protos = rc_type;
rc->enabled_protocols = rc_type;
rc_set_allowed_protocols(rc, rc_type);
rc_set_enabled_protocols(rc, rc_type);
if (!rc->driver_name)
rc->driver_name = MODULE_NAME;

Fájl megtekintése

@@ -15,12 +15,6 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <linux/delay.h>
@@ -42,7 +36,7 @@
#define REG_FLAG 0xd0
#define REG_CONFIG1 0xe0
/* Fault Mask */
/* fault mask */
#define FAULT_TIMEOUT (1<<0)
#define FAULT_OVERTEMP (1<<1)
#define FAULT_SHORT_CIRCUIT (1<<2)
@@ -53,7 +47,8 @@ enum led_enable {
MODE_FLASH = 0x3,
};
/* struct lm3560_flash
/**
* struct lm3560_flash
*
* @pdata: platform data
* @regmap: reg. map for i2c
@@ -98,7 +93,7 @@ static int lm3560_mode_ctrl(struct lm3560_flash *flash)
return rval;
}
/* led1/2 enable/disable */
/* led1/2 enable/disable */
static int lm3560_enable_ctrl(struct lm3560_flash *flash,
enum lm3560_led_id led_no, bool on)
{
@@ -168,7 +163,7 @@ static int lm3560_flash_brt_ctrl(struct lm3560_flash *flash,
return rval;
}
/* V4L2 controls */
/* v4l2 controls */
static int lm3560_get_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
{
struct lm3560_flash *flash = to_lm3560_flash(ctrl, led_no);
@@ -297,6 +292,7 @@ static int lm3560_init_controls(struct lm3560_flash *flash,
const struct v4l2_ctrl_ops *ops = &lm3560_led_ctrl_ops[led_no];
v4l2_ctrl_handler_init(hdl, 8);
/* flash mode */
v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_FLASH_LED_MODE,
V4L2_FLASH_LED_MODE_TORCH, ~0x7,
@@ -309,6 +305,7 @@ static int lm3560_init_controls(struct lm3560_flash *flash,
/* flash strobe */
v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_STROBE, 0, 0, 0, 0);
/* flash strobe stop */
v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0);
@@ -395,7 +392,7 @@ static int lm3560_init_device(struct lm3560_flash *flash)
rval = lm3560_mode_ctrl(flash);
if (rval < 0)
return rval;
/* Reset faults */
/* reset faults */
rval = regmap_read(flash->regmap, REG_FLAG, &reg_val);
return rval;
}
@@ -419,8 +416,7 @@ static int lm3560_probe(struct i2c_client *client,
/* if there is no platform data, use chip default value */
if (pdata == NULL) {
pdata =
kzalloc(sizeof(struct lm3560_platform_data), GFP_KERNEL);
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
if (pdata == NULL)
return -ENODEV;
pdata->peak = LM3560_PEAK_3600mA;

414
drivers/media/i2c/lm3646.c Normal file
Fájl megtekintése

@@ -0,0 +1,414 @@
/*
* drivers/media/i2c/lm3646.c
* General device driver for TI lm3646, Dual FLASH LED Driver
*
* Copyright (C) 2014 Texas Instruments
*
* Contact: Daniel Jeong <gshark.jeong@gmail.com>
* Ldd-Mlp <ldd-mlp@list.ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/regmap.h>
#include <linux/videodev2.h>
#include <media/lm3646.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
/* registers definitions */
#define REG_ENABLE 0x01
#define REG_TORCH_BR 0x05
#define REG_FLASH_BR 0x05
#define REG_FLASH_TOUT 0x04
#define REG_FLAG 0x08
#define REG_STROBE_SRC 0x06
#define REG_LED1_FLASH_BR 0x06
#define REG_LED1_TORCH_BR 0x07
#define MASK_ENABLE 0x03
#define MASK_TORCH_BR 0x70
#define MASK_FLASH_BR 0x0F
#define MASK_FLASH_TOUT 0x07
#define MASK_FLAG 0xFF
#define MASK_STROBE_SRC 0x80
/* Fault Mask */
#define FAULT_TIMEOUT (1<<0)
#define FAULT_SHORT_CIRCUIT (1<<1)
#define FAULT_UVLO (1<<2)
#define FAULT_IVFM (1<<3)
#define FAULT_OCP (1<<4)
#define FAULT_OVERTEMP (1<<5)
#define FAULT_NTC_TRIP (1<<6)
#define FAULT_OVP (1<<7)
enum led_mode {
MODE_SHDN = 0x0,
MODE_TORCH = 0x2,
MODE_FLASH = 0x3,
};
/*
* struct lm3646_flash
*
* @pdata: platform data
* @regmap: reg. map for i2c
* @lock: muxtex for serial access.
* @led_mode: V4L2 LED mode
* @ctrls_led: V4L2 contols
* @subdev_led: V4L2 subdev
* @mode_reg : mode register value
*/
struct lm3646_flash {
struct device *dev;
struct lm3646_platform_data *pdata;
struct regmap *regmap;
struct v4l2_ctrl_handler ctrls_led;
struct v4l2_subdev subdev_led;
u8 mode_reg;
};
#define to_lm3646_flash(_ctrl) \
container_of(_ctrl->handler, struct lm3646_flash, ctrls_led)
/* enable mode control */
static int lm3646_mode_ctrl(struct lm3646_flash *flash,
enum v4l2_flash_led_mode led_mode)
{
switch (led_mode) {
case V4L2_FLASH_LED_MODE_NONE:
return regmap_write(flash->regmap,
REG_ENABLE, flash->mode_reg | MODE_SHDN);
case V4L2_FLASH_LED_MODE_TORCH:
return regmap_write(flash->regmap,
REG_ENABLE, flash->mode_reg | MODE_TORCH);
case V4L2_FLASH_LED_MODE_FLASH:
return regmap_write(flash->regmap,
REG_ENABLE, flash->mode_reg | MODE_FLASH);
}
return -EINVAL;
}
/* V4L2 controls */
static int lm3646_get_ctrl(struct v4l2_ctrl *ctrl)
{
struct lm3646_flash *flash = to_lm3646_flash(ctrl);
unsigned int reg_val;
int rval;
if (ctrl->id != V4L2_CID_FLASH_FAULT)
return -EINVAL;
rval = regmap_read(flash->regmap, REG_FLAG, &reg_val);
if (rval < 0)
return rval;
ctrl->val = 0;
if (reg_val & FAULT_TIMEOUT)
ctrl->val |= V4L2_FLASH_FAULT_TIMEOUT;
if (reg_val & FAULT_SHORT_CIRCUIT)
ctrl->val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
if (reg_val & FAULT_UVLO)
ctrl->val |= V4L2_FLASH_FAULT_UNDER_VOLTAGE;
if (reg_val & FAULT_IVFM)
ctrl->val |= V4L2_FLASH_FAULT_INPUT_VOLTAGE;
if (reg_val & FAULT_OCP)
ctrl->val |= V4L2_FLASH_FAULT_OVER_CURRENT;
if (reg_val & FAULT_OVERTEMP)
ctrl->val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
if (reg_val & FAULT_NTC_TRIP)
ctrl->val |= V4L2_FLASH_FAULT_LED_OVER_TEMPERATURE;
if (reg_val & FAULT_OVP)
ctrl->val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
return 0;
}
static int lm3646_set_ctrl(struct v4l2_ctrl *ctrl)
{
struct lm3646_flash *flash = to_lm3646_flash(ctrl);
unsigned int reg_val;
int rval = -EINVAL;
switch (ctrl->id) {
case V4L2_CID_FLASH_LED_MODE:
if (ctrl->val != V4L2_FLASH_LED_MODE_FLASH)
return lm3646_mode_ctrl(flash, ctrl->val);
/* switch to SHDN mode before flash strobe on */
return lm3646_mode_ctrl(flash, V4L2_FLASH_LED_MODE_NONE);
case V4L2_CID_FLASH_STROBE_SOURCE:
return regmap_update_bits(flash->regmap,
REG_STROBE_SRC, MASK_STROBE_SRC,
(ctrl->val) << 7);
case V4L2_CID_FLASH_STROBE:
/* read and check current mode of chip to start flash */
rval = regmap_read(flash->regmap, REG_ENABLE, &reg_val);
if (rval < 0 || ((reg_val & MASK_ENABLE) != MODE_SHDN))
return rval;
/* flash on */
return lm3646_mode_ctrl(flash, V4L2_FLASH_LED_MODE_FLASH);
case V4L2_CID_FLASH_STROBE_STOP:
/*
* flash mode will be turned automatically
* from FLASH mode to SHDN mode after flash duration timeout
* read and check current mode of chip to stop flash
*/
rval = regmap_read(flash->regmap, REG_ENABLE, &reg_val);
if (rval < 0)
return rval;
if ((reg_val & MASK_ENABLE) == MODE_FLASH)
return lm3646_mode_ctrl(flash,
V4L2_FLASH_LED_MODE_NONE);
return rval;
case V4L2_CID_FLASH_TIMEOUT:
return regmap_update_bits(flash->regmap,
REG_FLASH_TOUT, MASK_FLASH_TOUT,
LM3646_FLASH_TOUT_ms_TO_REG
(ctrl->val));
case V4L2_CID_FLASH_INTENSITY:
return regmap_update_bits(flash->regmap,
REG_FLASH_BR, MASK_FLASH_BR,
LM3646_TOTAL_FLASH_BRT_uA_TO_REG
(ctrl->val));
case V4L2_CID_FLASH_TORCH_INTENSITY:
return regmap_update_bits(flash->regmap,
REG_TORCH_BR, MASK_TORCH_BR,
LM3646_TOTAL_TORCH_BRT_uA_TO_REG
(ctrl->val) << 4);
}
return -EINVAL;
}
static const struct v4l2_ctrl_ops lm3646_led_ctrl_ops = {
.g_volatile_ctrl = lm3646_get_ctrl,
.s_ctrl = lm3646_set_ctrl,
};
static int lm3646_init_controls(struct lm3646_flash *flash)
{
struct v4l2_ctrl *fault;
struct v4l2_ctrl_handler *hdl = &flash->ctrls_led;
const struct v4l2_ctrl_ops *ops = &lm3646_led_ctrl_ops;
v4l2_ctrl_handler_init(hdl, 8);
/* flash mode */
v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_FLASH_LED_MODE,
V4L2_FLASH_LED_MODE_TORCH, ~0x7,
V4L2_FLASH_LED_MODE_NONE);
/* flash source */
v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_FLASH_STROBE_SOURCE,
0x1, ~0x3, V4L2_FLASH_STROBE_SOURCE_SOFTWARE);
/* flash strobe */
v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_STROBE, 0, 0, 0, 0);
/* flash strobe stop */
v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0);
/* flash strobe timeout */
v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_TIMEOUT,
LM3646_FLASH_TOUT_MIN,
LM3646_FLASH_TOUT_MAX,
LM3646_FLASH_TOUT_STEP, flash->pdata->flash_timeout);
/* max flash current */
v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_INTENSITY,
LM3646_TOTAL_FLASH_BRT_MIN,
LM3646_TOTAL_FLASH_BRT_MAX,
LM3646_TOTAL_FLASH_BRT_STEP,
LM3646_TOTAL_FLASH_BRT_MAX);
/* max torch current */
v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_TORCH_INTENSITY,
LM3646_TOTAL_TORCH_BRT_MIN,
LM3646_TOTAL_TORCH_BRT_MAX,
LM3646_TOTAL_TORCH_BRT_STEP,
LM3646_TOTAL_TORCH_BRT_MAX);
/* fault */
fault = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_FAULT, 0,
V4L2_FLASH_FAULT_OVER_VOLTAGE
| V4L2_FLASH_FAULT_OVER_TEMPERATURE
| V4L2_FLASH_FAULT_SHORT_CIRCUIT
| V4L2_FLASH_FAULT_TIMEOUT, 0, 0);
if (fault != NULL)
fault->flags |= V4L2_CTRL_FLAG_VOLATILE;
if (hdl->error)
return hdl->error;
flash->subdev_led.ctrl_handler = hdl;
return 0;
}
/* initialize device */
static const struct v4l2_subdev_ops lm3646_ops = {
.core = NULL,
};
static const struct regmap_config lm3646_regmap = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0xFF,
};
static int lm3646_subdev_init(struct lm3646_flash *flash)
{
struct i2c_client *client = to_i2c_client(flash->dev);
int rval;
v4l2_i2c_subdev_init(&flash->subdev_led, client, &lm3646_ops);
flash->subdev_led.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
strcpy(flash->subdev_led.name, LM3646_NAME);
rval = lm3646_init_controls(flash);
if (rval)
goto err_out;
rval = media_entity_init(&flash->subdev_led.entity, 0, NULL, 0);
if (rval < 0)
goto err_out;
flash->subdev_led.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;
return rval;
err_out:
v4l2_ctrl_handler_free(&flash->ctrls_led);
return rval;
}
static int lm3646_init_device(struct lm3646_flash *flash)
{
unsigned int reg_val;
int rval;
/* read the value of mode register to reduce redundant i2c accesses */
rval = regmap_read(flash->regmap, REG_ENABLE, &reg_val);
if (rval < 0)
return rval;
flash->mode_reg = reg_val & 0xfc;
/* output disable */
rval = lm3646_mode_ctrl(flash, V4L2_FLASH_LED_MODE_NONE);
if (rval < 0)
return rval;
/*
* LED1 flash current setting
* LED2 flash current = Total(Max) flash current - LED1 flash current
*/
rval = regmap_update_bits(flash->regmap,
REG_LED1_FLASH_BR, 0x7F,
LM3646_LED1_FLASH_BRT_uA_TO_REG
(flash->pdata->led1_flash_brt));
if (rval < 0)
return rval;
/*
* LED1 torch current setting
* LED2 torch current = Total(Max) torch current - LED1 torch current
*/
rval = regmap_update_bits(flash->regmap,
REG_LED1_TORCH_BR, 0x7F,
LM3646_LED1_TORCH_BRT_uA_TO_REG
(flash->pdata->led1_torch_brt));
if (rval < 0)
return rval;
/* Reset flag register */
return regmap_read(flash->regmap, REG_FLAG, &reg_val);
}
static int lm3646_probe(struct i2c_client *client,
const struct i2c_device_id *devid)
{
struct lm3646_flash *flash;
struct lm3646_platform_data *pdata = dev_get_platdata(&client->dev);
int rval;
flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
if (flash == NULL)
return -ENOMEM;
flash->regmap = devm_regmap_init_i2c(client, &lm3646_regmap);
if (IS_ERR(flash->regmap))
return PTR_ERR(flash->regmap);
/* check device tree if there is no platform data */
if (pdata == NULL) {
pdata = devm_kzalloc(&client->dev,
sizeof(struct lm3646_platform_data),
GFP_KERNEL);
if (pdata == NULL)
return -ENOMEM;
/* use default data in case of no platform data */
pdata->flash_timeout = LM3646_FLASH_TOUT_MAX;
pdata->led1_torch_brt = LM3646_LED1_TORCH_BRT_MAX;
pdata->led1_flash_brt = LM3646_LED1_FLASH_BRT_MAX;
}
flash->pdata = pdata;
flash->dev = &client->dev;
rval = lm3646_subdev_init(flash);
if (rval < 0)
return rval;
rval = lm3646_init_device(flash);
if (rval < 0)
return rval;
i2c_set_clientdata(client, flash);
return 0;
}
static int lm3646_remove(struct i2c_client *client)
{
struct lm3646_flash *flash = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(&flash->subdev_led);
v4l2_ctrl_handler_free(&flash->ctrls_led);
media_entity_cleanup(&flash->subdev_led.entity);
return 0;
}
static const struct i2c_device_id lm3646_id_table[] = {
{LM3646_NAME, 0},
{}
};
MODULE_DEVICE_TABLE(i2c, lm3646_id_table);
static struct i2c_driver lm3646_i2c_driver = {
.driver = {
.name = LM3646_NAME,
},
.probe = lm3646_probe,
.remove = lm3646_remove,
.id_table = lm3646_id_table,
};
module_i2c_driver(lm3646_i2c_driver);
MODULE_AUTHOR("Daniel Jeong <gshark.jeong@gmail.com>");
MODULE_AUTHOR("Ldd Mlp <ldd-mlp@list.ti.com>");
MODULE_DESCRIPTION("Texas Instruments LM3646 Dual Flash LED driver");
MODULE_LICENSE("GPL");

Fájl megtekintése

@@ -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)) {

Fájl megtekintése

@@ -12,9 +12,11 @@
* published by the Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/log2.h>
#include <linux/module.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <linux/v4l2-mediabus.h>
@@ -55,6 +57,7 @@
#define MT9T001_OUTPUT_CONTROL_SYNC (1 << 0)
#define MT9T001_OUTPUT_CONTROL_CHIP_ENABLE (1 << 1)
#define MT9T001_OUTPUT_CONTROL_TEST_DATA (1 << 6)
#define MT9T001_OUTPUT_CONTROL_DEF 0x0002
#define MT9T001_SHUTTER_WIDTH_HIGH 0x08
#define MT9T001_SHUTTER_WIDTH_LOW 0x09
#define MT9T001_SHUTTER_WIDTH_MIN 1
@@ -116,6 +119,12 @@ struct mt9t001 {
struct v4l2_subdev subdev;
struct media_pad pad;
struct clk *clk;
struct regulator_bulk_data regulators[2];
struct mutex power_lock; /* lock to protect power_count */
int power_count;
struct v4l2_mbus_framefmt format;
struct v4l2_rect crop;
@@ -159,6 +168,77 @@ static int mt9t001_set_output_control(struct mt9t001 *mt9t001, u16 clear,
return 0;
}
static int mt9t001_reset(struct mt9t001 *mt9t001)
{
struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
int ret;
/* Reset the chip and stop data read out */
ret = mt9t001_write(client, MT9T001_RESET, 1);
if (ret < 0)
return ret;
ret = mt9t001_write(client, MT9T001_RESET, 0);
if (ret < 0)
return ret;
mt9t001->output_control = MT9T001_OUTPUT_CONTROL_DEF;
return mt9t001_set_output_control(mt9t001,
MT9T001_OUTPUT_CONTROL_CHIP_ENABLE,
0);
}
static int mt9t001_power_on(struct mt9t001 *mt9t001)
{
int ret;
/* Bring up the supplies */
ret = regulator_bulk_enable(ARRAY_SIZE(mt9t001->regulators),
mt9t001->regulators);
if (ret < 0)
return ret;
/* Enable clock */
ret = clk_prepare_enable(mt9t001->clk);
if (ret < 0)
regulator_bulk_disable(ARRAY_SIZE(mt9t001->regulators),
mt9t001->regulators);
return ret;
}
static void mt9t001_power_off(struct mt9t001 *mt9t001)
{
regulator_bulk_disable(ARRAY_SIZE(mt9t001->regulators),
mt9t001->regulators);
clk_disable_unprepare(mt9t001->clk);
}
static int __mt9t001_set_power(struct mt9t001 *mt9t001, bool on)
{
struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
int ret;
if (!on) {
mt9t001_power_off(mt9t001);
return 0;
}
ret = mt9t001_power_on(mt9t001);
if (ret < 0)
return ret;
ret = mt9t001_reset(mt9t001);
if (ret < 0) {
dev_err(&client->dev, "Failed to reset the camera\n");
return ret;
}
return v4l2_ctrl_handler_setup(&mt9t001->ctrls);
}
/* -----------------------------------------------------------------------------
* V4L2 subdev video operations
*/
@@ -195,6 +275,7 @@ static int mt9t001_s_stream(struct v4l2_subdev *subdev, int enable)
{
const u16 mode = MT9T001_OUTPUT_CONTROL_CHIP_ENABLE;
struct i2c_client *client = v4l2_get_subdevdata(subdev);
struct mt9t001_platform_data *pdata = client->dev.platform_data;
struct mt9t001 *mt9t001 = to_mt9t001(subdev);
struct v4l2_mbus_framefmt *format = &mt9t001->format;
struct v4l2_rect *crop = &mt9t001->crop;
@@ -205,6 +286,14 @@ static int mt9t001_s_stream(struct v4l2_subdev *subdev, int enable)
if (!enable)
return mt9t001_set_output_control(mt9t001, mode, 0);
/* Configure the pixel clock polarity */
if (pdata->clk_pol) {
ret = mt9t001_write(client, MT9T001_PIXEL_CLOCK,
MT9T001_PIXEL_CLOCK_INVERT);
if (ret < 0)
return ret;
}
/* Configure the window size and row/column bin */
hratio = DIV_ROUND_CLOSEST(crop->width, format->width);
vratio = DIV_ROUND_CLOSEST(crop->height, format->height);
@@ -629,10 +718,68 @@ static const struct v4l2_ctrl_config mt9t001_gains[] = {
},
};
/* -----------------------------------------------------------------------------
* V4L2 subdev core operations
*/
static int mt9t001_set_power(struct v4l2_subdev *subdev, int on)
{
struct mt9t001 *mt9t001 = to_mt9t001(subdev);
int ret = 0;
mutex_lock(&mt9t001->power_lock);
/* If the power count is modified from 0 to != 0 or from != 0 to 0,
* update the power state.
*/
if (mt9t001->power_count == !on) {
ret = __mt9t001_set_power(mt9t001, !!on);
if (ret < 0)
goto out;
}
/* Update the power count. */
mt9t001->power_count += on ? 1 : -1;
WARN_ON(mt9t001->power_count < 0);
out:
mutex_unlock(&mt9t001->power_lock);
return ret;
}
/* -----------------------------------------------------------------------------
* V4L2 subdev internal operations
*/
static int mt9t001_registered(struct v4l2_subdev *subdev)
{
struct i2c_client *client = v4l2_get_subdevdata(subdev);
struct mt9t001 *mt9t001 = to_mt9t001(subdev);
s32 data;
int ret;
ret = mt9t001_power_on(mt9t001);
if (ret < 0) {
dev_err(&client->dev, "MT9T001 power up failed\n");
return ret;
}
/* Read out the chip version register */
data = mt9t001_read(client, MT9T001_CHIP_VERSION);
mt9t001_power_off(mt9t001);
if (data != MT9T001_CHIP_ID) {
dev_err(&client->dev,
"MT9T001 not detected, wrong version 0x%04x\n", data);
return -ENODEV;
}
dev_info(&client->dev, "MT9T001 detected at address 0x%02x\n",
client->addr);
return 0;
}
static int mt9t001_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
{
struct v4l2_mbus_framefmt *format;
@@ -651,9 +798,18 @@ static int mt9t001_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
format->field = V4L2_FIELD_NONE;
format->colorspace = V4L2_COLORSPACE_SRGB;
return 0;
return mt9t001_set_power(subdev, 1);
}
static int mt9t001_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
{
return mt9t001_set_power(subdev, 0);
}
static struct v4l2_subdev_core_ops mt9t001_subdev_core_ops = {
.s_power = mt9t001_set_power,
};
static struct v4l2_subdev_video_ops mt9t001_subdev_video_ops = {
.s_stream = mt9t001_s_stream,
};
@@ -668,58 +824,17 @@ static struct v4l2_subdev_pad_ops mt9t001_subdev_pad_ops = {
};
static struct v4l2_subdev_ops mt9t001_subdev_ops = {
.core = &mt9t001_subdev_core_ops,
.video = &mt9t001_subdev_video_ops,
.pad = &mt9t001_subdev_pad_ops,
};
static struct v4l2_subdev_internal_ops mt9t001_subdev_internal_ops = {
.registered = mt9t001_registered,
.open = mt9t001_open,
.close = mt9t001_close,
};
static int mt9t001_video_probe(struct i2c_client *client)
{
struct mt9t001_platform_data *pdata = client->dev.platform_data;
s32 data;
int ret;
dev_info(&client->dev, "Probing MT9T001 at address 0x%02x\n",
client->addr);
/* Reset the chip and stop data read out */
ret = mt9t001_write(client, MT9T001_RESET, 1);
if (ret < 0)
return ret;
ret = mt9t001_write(client, MT9T001_RESET, 0);
if (ret < 0)
return ret;
ret = mt9t001_write(client, MT9T001_OUTPUT_CONTROL, 0);
if (ret < 0)
return ret;
/* Configure the pixel clock polarity */
if (pdata->clk_pol) {
ret = mt9t001_write(client, MT9T001_PIXEL_CLOCK,
MT9T001_PIXEL_CLOCK_INVERT);
if (ret < 0)
return ret;
}
/* Read and check the sensor version */
data = mt9t001_read(client, MT9T001_CHIP_VERSION);
if (data != MT9T001_CHIP_ID) {
dev_err(&client->dev, "MT9T001 not detected, wrong version "
"0x%04x\n", data);
return -ENODEV;
}
dev_info(&client->dev, "MT9T001 detected at address 0x%02x\n",
client->addr);
return ret;
}
static int mt9t001_probe(struct i2c_client *client,
const struct i2c_device_id *did)
{
@@ -740,14 +855,28 @@ static int mt9t001_probe(struct i2c_client *client,
return -EIO;
}
ret = mt9t001_video_probe(client);
if (ret < 0)
return ret;
mt9t001 = devm_kzalloc(&client->dev, sizeof(*mt9t001), GFP_KERNEL);
if (!mt9t001)
return -ENOMEM;
mutex_init(&mt9t001->power_lock);
mt9t001->output_control = MT9T001_OUTPUT_CONTROL_DEF;
mt9t001->regulators[0].supply = "vdd";
mt9t001->regulators[1].supply = "vaa";
ret = devm_regulator_bulk_get(&client->dev, 2, mt9t001->regulators);
if (ret < 0) {
dev_err(&client->dev, "Unable to get regulators\n");
return ret;
}
mt9t001->clk = devm_clk_get(&client->dev, NULL);
if (IS_ERR(mt9t001->clk)) {
dev_err(&client->dev, "Unable to get clock\n");
return PTR_ERR(mt9t001->clk);
}
v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) +
ARRAY_SIZE(mt9t001_gains) + 4);

Fájl megtekintése

@@ -1,7 +1,7 @@
/*
* mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor
*
* Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com)
* Copyright (c) 2009 Mauro Carvalho Chehab
* This code is placed under the terms of the GNU General Public License v2
*/
@@ -16,7 +16,7 @@
#include <media/mt9v011.h>
MODULE_DESCRIPTION("Micron mt9v011 sensor driver");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
MODULE_AUTHOR("Mauro Carvalho Chehab");
MODULE_LICENSE("GPL");
static int debug;

Fájl megtekintése

@@ -317,8 +317,14 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032)
struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
int ret;
clk_set_rate(mt9v032->clk, mt9v032->sysclk);
clk_prepare_enable(mt9v032->clk);
ret = clk_set_rate(mt9v032->clk, mt9v032->sysclk);
if (ret < 0)
return ret;
ret = clk_prepare_enable(mt9v032->clk);
if (ret)
return ret;
udelay(1);
/* Reset the chip and stop data read out */

Fájl megtekintése

@@ -8,7 +8,7 @@
* and HeungJun Kim <riverful.kim@samsung.com>.
*
* Based on mt9v011 Micron Digital Image Sensor driver
* Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com)
* Copyright (c) 2009 Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

Fájl megtekintése

@@ -217,8 +217,8 @@ static void ths8200_core_init(struct v4l2_subdev *sd)
/* Disable embedded syncs on the output by setting
* the amplitude to zero for all channels.
*/
ths8200_write(sd, THS8200_DTG1_Y_SYNC_MSB, 0x2a);
ths8200_write(sd, THS8200_DTG1_CBCR_SYNC_MSB, 0x2a);
ths8200_write(sd, THS8200_DTG1_Y_SYNC_MSB, 0x00);
ths8200_write(sd, THS8200_DTG1_CBCR_SYNC_MSB, 0x00);
}
static void ths8200_setup(struct v4l2_subdev *sd, struct v4l2_bt_timings *bt)
@@ -318,15 +318,15 @@ static void ths8200_setup(struct v4l2_subdev *sd, struct v4l2_bt_timings *bt)
(htotal(bt) >> 8) & 0x1f);
ths8200_write(sd, THS8200_DTG2_HLENGTH_HDLY_LSB, htotal(bt));
/* v sync width transmitted */
ths8200_write(sd, THS8200_DTG2_VLENGTH1_LSB, (bt->vsync) & 0xff);
/* v sync width transmitted (must add 1 to get correct output) */
ths8200_write(sd, THS8200_DTG2_VLENGTH1_LSB, (bt->vsync + 1) & 0xff);
ths8200_write_and_or(sd, THS8200_DTG2_VLENGTH1_MSB_VDLY1_MSB, 0x3f,
((bt->vsync) >> 2) & 0xc0);
((bt->vsync + 1) >> 2) & 0xc0);
/* The pixel value v sync is asserted on */
/* The pixel value v sync is asserted on (must add 1 to get correct output) */
ths8200_write_and_or(sd, THS8200_DTG2_VLENGTH1_MSB_VDLY1_MSB, 0xf8,
(vtotal(bt)>>8) & 0x7);
ths8200_write(sd, THS8200_DTG2_VDLY1_LSB, vtotal(bt));
((vtotal(bt) + 1) >> 8) & 0x7);
ths8200_write(sd, THS8200_DTG2_VDLY1_LSB, vtotal(bt) + 1);
/* For progressive video vlength2 must be set to all 0 and vdly2 must
* be set to all 1.
@@ -336,11 +336,11 @@ static void ths8200_setup(struct v4l2_subdev *sd, struct v4l2_bt_timings *bt)
ths8200_write(sd, THS8200_DTG2_VDLY2_LSB, 0xff);
/* Internal delay factors to synchronize the sync pulses and the data */
/* Experimental values delays (hor 4, ver 1) */
ths8200_write(sd, THS8200_DTG2_HS_IN_DLY_MSB, (htotal(bt)>>8) & 0x1f);
ths8200_write(sd, THS8200_DTG2_HS_IN_DLY_LSB, (htotal(bt) - 4) & 0xff);
/* Experimental values delays (hor 0, ver 0) */
ths8200_write(sd, THS8200_DTG2_HS_IN_DLY_MSB, 0);
ths8200_write(sd, THS8200_DTG2_HS_IN_DLY_LSB, 0);
ths8200_write(sd, THS8200_DTG2_VS_IN_DLY_MSB, 0);
ths8200_write(sd, THS8200_DTG2_VS_IN_DLY_LSB, 1);
ths8200_write(sd, THS8200_DTG2_VS_IN_DLY_LSB, 0);
/* Polarity of received and transmitted sync signals */
if (bt->polarities & V4L2_DV_HSYNC_POS_POL) {
@@ -356,7 +356,7 @@ static void ths8200_setup(struct v4l2_subdev *sd, struct v4l2_bt_timings *bt)
/* Timing of video input bus is derived from HS, VS, and FID dedicated
* inputs
*/
ths8200_write(sd, THS8200_DTG2_CNTL, 0x47 | polarity);
ths8200_write(sd, THS8200_DTG2_CNTL, 0x44 | polarity);
/* leave reset */
ths8200_s_stream(sd, true);

Fájl megtekintése

@@ -16,9 +16,9 @@
#include "tvp5150_reg.h"
#define TVP5150_H_MAX 720
#define TVP5150_V_MAX_525_60 480
#define TVP5150_V_MAX_OTHERS 576
#define TVP5150_H_MAX 720U
#define TVP5150_V_MAX_525_60 480U
#define TVP5150_V_MAX_OTHERS 576U
#define TVP5150_MAX_CROP_LEFT 511
#define TVP5150_MAX_CROP_TOP 127
#define TVP5150_CROP_SHIFT 2
@@ -29,7 +29,7 @@ MODULE_LICENSE("GPL");
static int debug;
module_param(debug, int, 0);
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-2)");
struct tvp5150 {