Commit 9d1d166f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'media/v4.10-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media fixes from Mauro Carvalho Chehab:

 - fix a regression on tvp5150 causing failures at input selection and
   image glitches

 - CEC was moved out of staging for v4.10. Fix some bugs on it while not
   too late

 - fix a regression on pctv452e caused by VM stack changes

 - fix suspend issued with smiapp

 - fix a regression on cobalt driver

 - fix some warnings and Kconfig issues with some random configs.

* tag 'media/v4.10-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media:
  [media] s5k4ecgx: select CRC32 helper
  [media] dvb: avoid warning in dvb_net
  [media] v4l: tvp5150: Don't override output pinmuxing at stream on/off time
  [media] v4l: tvp5150: Fix comment regarding output pin muxing
  [media] v4l: tvp5150: Reset device at probe time, not in get/set format handlers
  [media] pctv452e: move buffer to heap, no mutex
  [media] media/cobalt: use pci_irq_allocate_vectors
  [media] cec: fix race between configuring and unconfiguring
  [media] cec: move cec_report_phys_addr into cec_config_thread_func
  [media] cec: replace cec_report_features by cec_fill_msg_report_features
  [media] cec: update log_addr[] before finishing configuration
  [media] cec: CEC_MSG_GIVE_FEATURES should abort for CEC version < 2
  [media] cec: when canceling a message, don't overwrite old status info
  [media] cec: fix report_current_latency
  [media] smiapp: Make suspend and resume functions __maybe_unused
  [media] smiapp: Implement power-on and power-off sequences without runtime PM
parents b84f0279 0e0694ff
...@@ -30,8 +30,9 @@ ...@@ -30,8 +30,9 @@
#include "cec-priv.h" #include "cec-priv.h"
static int cec_report_features(struct cec_adapter *adap, unsigned int la_idx); static void cec_fill_msg_report_features(struct cec_adapter *adap,
static int cec_report_phys_addr(struct cec_adapter *adap, unsigned int la_idx); struct cec_msg *msg,
unsigned int la_idx);
/* /*
* 400 ms is the time it takes for one 16 byte message to be * 400 ms is the time it takes for one 16 byte message to be
...@@ -288,10 +289,10 @@ static void cec_data_cancel(struct cec_data *data) ...@@ -288,10 +289,10 @@ static void cec_data_cancel(struct cec_data *data)
/* Mark it as an error */ /* Mark it as an error */
data->msg.tx_ts = ktime_get_ns(); data->msg.tx_ts = ktime_get_ns();
data->msg.tx_status = CEC_TX_STATUS_ERROR | data->msg.tx_status |= CEC_TX_STATUS_ERROR |
CEC_TX_STATUS_MAX_RETRIES; CEC_TX_STATUS_MAX_RETRIES;
data->msg.tx_error_cnt++;
data->attempts = 0; data->attempts = 0;
data->msg.tx_error_cnt = 1;
/* Queue transmitted message for monitoring purposes */ /* Queue transmitted message for monitoring purposes */
cec_queue_msg_monitor(data->adap, &data->msg, 1); cec_queue_msg_monitor(data->adap, &data->msg, 1);
...@@ -851,7 +852,7 @@ static const u8 cec_msg_size[256] = { ...@@ -851,7 +852,7 @@ static const u8 cec_msg_size[256] = {
[CEC_MSG_REQUEST_ARC_TERMINATION] = 2 | DIRECTED, [CEC_MSG_REQUEST_ARC_TERMINATION] = 2 | DIRECTED,
[CEC_MSG_TERMINATE_ARC] = 2 | DIRECTED, [CEC_MSG_TERMINATE_ARC] = 2 | DIRECTED,
[CEC_MSG_REQUEST_CURRENT_LATENCY] = 4 | BCAST, [CEC_MSG_REQUEST_CURRENT_LATENCY] = 4 | BCAST,
[CEC_MSG_REPORT_CURRENT_LATENCY] = 7 | BCAST, [CEC_MSG_REPORT_CURRENT_LATENCY] = 6 | BCAST,
[CEC_MSG_CDC_MESSAGE] = 2 | BCAST, [CEC_MSG_CDC_MESSAGE] = 2 | BCAST,
}; };
...@@ -1250,30 +1251,49 @@ static int cec_config_thread_func(void *arg) ...@@ -1250,30 +1251,49 @@ static int cec_config_thread_func(void *arg)
for (i = 1; i < las->num_log_addrs; i++) for (i = 1; i < las->num_log_addrs; i++)
las->log_addr[i] = CEC_LOG_ADDR_INVALID; las->log_addr[i] = CEC_LOG_ADDR_INVALID;
} }
for (i = las->num_log_addrs; i < CEC_MAX_LOG_ADDRS; i++)
las->log_addr[i] = CEC_LOG_ADDR_INVALID;
adap->is_configured = true; adap->is_configured = true;
adap->is_configuring = false; adap->is_configuring = false;
cec_post_state_event(adap); cec_post_state_event(adap);
mutex_unlock(&adap->lock);
/*
* Now post the Report Features and Report Physical Address broadcast
* messages. Note that these are non-blocking transmits, meaning that
* they are just queued up and once adap->lock is unlocked the main
* thread will kick in and start transmitting these.
*
* If after this function is done (but before one or more of these
* messages are actually transmitted) the CEC adapter is unconfigured,
* then any remaining messages will be dropped by the main thread.
*/
for (i = 0; i < las->num_log_addrs; i++) { for (i = 0; i < las->num_log_addrs; i++) {
struct cec_msg msg = {};
if (las->log_addr[i] == CEC_LOG_ADDR_INVALID || if (las->log_addr[i] == CEC_LOG_ADDR_INVALID ||
(las->flags & CEC_LOG_ADDRS_FL_CDC_ONLY)) (las->flags & CEC_LOG_ADDRS_FL_CDC_ONLY))
continue; continue;
/* msg.msg[0] = (las->log_addr[i] << 4) | 0x0f;
* Report Features must come first according
* to CEC 2.0 /* Report Features must come first according to CEC 2.0 */
*/ if (las->log_addr[i] != CEC_LOG_ADDR_UNREGISTERED &&
if (las->log_addr[i] != CEC_LOG_ADDR_UNREGISTERED) adap->log_addrs.cec_version >= CEC_OP_CEC_VERSION_2_0) {
cec_report_features(adap, i); cec_fill_msg_report_features(adap, &msg, i);
cec_report_phys_addr(adap, i); cec_transmit_msg_fh(adap, &msg, NULL, false);
}
/* Report Physical Address */
cec_msg_report_physical_addr(&msg, adap->phys_addr,
las->primary_device_type[i]);
dprintk(2, "config: la %d pa %x.%x.%x.%x\n",
las->log_addr[i],
cec_phys_addr_exp(adap->phys_addr));
cec_transmit_msg_fh(adap, &msg, NULL, false);
} }
for (i = las->num_log_addrs; i < CEC_MAX_LOG_ADDRS; i++)
las->log_addr[i] = CEC_LOG_ADDR_INVALID;
mutex_lock(&adap->lock);
adap->kthread_config = NULL; adap->kthread_config = NULL;
mutex_unlock(&adap->lock);
complete(&adap->config_completion); complete(&adap->config_completion);
mutex_unlock(&adap->lock);
return 0; return 0;
unconfigure: unconfigure:
...@@ -1526,52 +1546,32 @@ EXPORT_SYMBOL_GPL(cec_s_log_addrs); ...@@ -1526,52 +1546,32 @@ EXPORT_SYMBOL_GPL(cec_s_log_addrs);
/* High-level core CEC message handling */ /* High-level core CEC message handling */
/* Transmit the Report Features message */ /* Fill in the Report Features message */
static int cec_report_features(struct cec_adapter *adap, unsigned int la_idx) static void cec_fill_msg_report_features(struct cec_adapter *adap,
struct cec_msg *msg,
unsigned int la_idx)
{ {
struct cec_msg msg = { };
const struct cec_log_addrs *las = &adap->log_addrs; const struct cec_log_addrs *las = &adap->log_addrs;
const u8 *features = las->features[la_idx]; const u8 *features = las->features[la_idx];
bool op_is_dev_features = false; bool op_is_dev_features = false;
unsigned int idx; unsigned int idx;
/* This is 2.0 and up only */
if (adap->log_addrs.cec_version < CEC_OP_CEC_VERSION_2_0)
return 0;
/* Report Features */ /* Report Features */
msg.msg[0] = (las->log_addr[la_idx] << 4) | 0x0f; msg->msg[0] = (las->log_addr[la_idx] << 4) | 0x0f;
msg.len = 4; msg->len = 4;
msg.msg[1] = CEC_MSG_REPORT_FEATURES; msg->msg[1] = CEC_MSG_REPORT_FEATURES;
msg.msg[2] = adap->log_addrs.cec_version; msg->msg[2] = adap->log_addrs.cec_version;
msg.msg[3] = las->all_device_types[la_idx]; msg->msg[3] = las->all_device_types[la_idx];
/* Write RC Profiles first, then Device Features */ /* Write RC Profiles first, then Device Features */
for (idx = 0; idx < ARRAY_SIZE(las->features[0]); idx++) { for (idx = 0; idx < ARRAY_SIZE(las->features[0]); idx++) {
msg.msg[msg.len++] = features[idx]; msg->msg[msg->len++] = features[idx];
if ((features[idx] & CEC_OP_FEAT_EXT) == 0) { if ((features[idx] & CEC_OP_FEAT_EXT) == 0) {
if (op_is_dev_features) if (op_is_dev_features)
break; break;
op_is_dev_features = true; op_is_dev_features = true;
} }
} }
return cec_transmit_msg(adap, &msg, false);
}
/* Transmit the Report Physical Address message */
static int cec_report_phys_addr(struct cec_adapter *adap, unsigned int la_idx)
{
const struct cec_log_addrs *las = &adap->log_addrs;
struct cec_msg msg = { };
/* Report Physical Address */
msg.msg[0] = (las->log_addr[la_idx] << 4) | 0x0f;
cec_msg_report_physical_addr(&msg, adap->phys_addr,
las->primary_device_type[la_idx]);
dprintk(2, "config: la %d pa %x.%x.%x.%x\n",
las->log_addr[la_idx],
cec_phys_addr_exp(adap->phys_addr));
return cec_transmit_msg(adap, &msg, false);
} }
/* Transmit the Feature Abort message */ /* Transmit the Feature Abort message */
...@@ -1777,9 +1777,10 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, ...@@ -1777,9 +1777,10 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
} }
case CEC_MSG_GIVE_FEATURES: case CEC_MSG_GIVE_FEATURES:
if (adap->log_addrs.cec_version >= CEC_OP_CEC_VERSION_2_0) if (adap->log_addrs.cec_version < CEC_OP_CEC_VERSION_2_0)
return cec_report_features(adap, la_idx); return cec_feature_abort(adap, msg);
return 0; cec_fill_msg_report_features(adap, &tx_cec_msg, la_idx);
return cec_transmit_msg(adap, &tx_cec_msg, false);
default: default:
/* /*
......
...@@ -719,6 +719,9 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h, ...@@ -719,6 +719,9 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
skb_copy_from_linear_data(h->priv->ule_skb, dest_addr, skb_copy_from_linear_data(h->priv->ule_skb, dest_addr,
ETH_ALEN); ETH_ALEN);
skb_pull(h->priv->ule_skb, ETH_ALEN); skb_pull(h->priv->ule_skb, ETH_ALEN);
} else {
/* dest_addr buffer is only valid if h->priv->ule_dbit == 0 */
eth_zero_addr(dest_addr);
} }
/* Handle ULE Extension Headers. */ /* Handle ULE Extension Headers. */
...@@ -750,16 +753,8 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h, ...@@ -750,16 +753,8 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
if (!h->priv->ule_bridged) { if (!h->priv->ule_bridged) {
skb_push(h->priv->ule_skb, ETH_HLEN); skb_push(h->priv->ule_skb, ETH_HLEN);
h->ethh = (struct ethhdr *)h->priv->ule_skb->data; h->ethh = (struct ethhdr *)h->priv->ule_skb->data;
if (!h->priv->ule_dbit) { memcpy(h->ethh->h_dest, dest_addr, ETH_ALEN);
/* eth_zero_addr(h->ethh->h_source);
* dest_addr buffer is only valid if
* h->priv->ule_dbit == 0
*/
memcpy(h->ethh->h_dest, dest_addr, ETH_ALEN);
eth_zero_addr(h->ethh->h_source);
} else /* zeroize source and dest */
memset(h->ethh, 0, ETH_ALEN * 2);
h->ethh->h_proto = htons(h->priv->ule_sndu_type); h->ethh->h_proto = htons(h->priv->ule_sndu_type);
} }
/* else: skb is in correct state; nothing to do. */ /* else: skb is in correct state; nothing to do. */
......
...@@ -655,6 +655,7 @@ config VIDEO_S5K6A3 ...@@ -655,6 +655,7 @@ config VIDEO_S5K6A3
config VIDEO_S5K4ECGX config VIDEO_S5K4ECGX
tristate "Samsung S5K4ECGX sensor support" tristate "Samsung S5K4ECGX sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
select CRC32
---help--- ---help---
This is a V4L2 sensor-level driver for Samsung S5K4ECGX 5M This is a V4L2 sensor-level driver for Samsung S5K4ECGX 5M
camera sensor with an embedded SoC image signal processor. camera sensor with an embedded SoC image signal processor.
......
...@@ -2741,9 +2741,7 @@ static const struct v4l2_subdev_internal_ops smiapp_internal_ops = { ...@@ -2741,9 +2741,7 @@ static const struct v4l2_subdev_internal_ops smiapp_internal_ops = {
* I2C Driver * I2C Driver
*/ */
#ifdef CONFIG_PM static int __maybe_unused smiapp_suspend(struct device *dev)
static int smiapp_suspend(struct device *dev)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct v4l2_subdev *subdev = i2c_get_clientdata(client); struct v4l2_subdev *subdev = i2c_get_clientdata(client);
...@@ -2768,7 +2766,7 @@ static int smiapp_suspend(struct device *dev) ...@@ -2768,7 +2766,7 @@ static int smiapp_suspend(struct device *dev)
return 0; return 0;
} }
static int smiapp_resume(struct device *dev) static int __maybe_unused smiapp_resume(struct device *dev)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct v4l2_subdev *subdev = i2c_get_clientdata(client); struct v4l2_subdev *subdev = i2c_get_clientdata(client);
...@@ -2783,13 +2781,6 @@ static int smiapp_resume(struct device *dev) ...@@ -2783,13 +2781,6 @@ static int smiapp_resume(struct device *dev)
return rval; return rval;
} }
#else
#define smiapp_suspend NULL
#define smiapp_resume NULL
#endif /* CONFIG_PM */
static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev) static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev)
{ {
struct smiapp_hwconfig *hwcfg; struct smiapp_hwconfig *hwcfg;
...@@ -2913,13 +2904,9 @@ static int smiapp_probe(struct i2c_client *client, ...@@ -2913,13 +2904,9 @@ static int smiapp_probe(struct i2c_client *client,
if (IS_ERR(sensor->xshutdown)) if (IS_ERR(sensor->xshutdown))
return PTR_ERR(sensor->xshutdown); return PTR_ERR(sensor->xshutdown);
pm_runtime_enable(&client->dev); rval = smiapp_power_on(&client->dev);
if (rval < 0)
rval = pm_runtime_get_sync(&client->dev); return rval;
if (rval < 0) {
rval = -ENODEV;
goto out_power_off;
}
rval = smiapp_identify_module(sensor); rval = smiapp_identify_module(sensor);
if (rval) { if (rval) {
...@@ -3100,6 +3087,9 @@ static int smiapp_probe(struct i2c_client *client, ...@@ -3100,6 +3087,9 @@ static int smiapp_probe(struct i2c_client *client,
if (rval < 0) if (rval < 0)
goto out_media_entity_cleanup; goto out_media_entity_cleanup;
pm_runtime_set_active(&client->dev);
pm_runtime_get_noresume(&client->dev);
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev, 1000); pm_runtime_set_autosuspend_delay(&client->dev, 1000);
pm_runtime_use_autosuspend(&client->dev); pm_runtime_use_autosuspend(&client->dev);
pm_runtime_put_autosuspend(&client->dev); pm_runtime_put_autosuspend(&client->dev);
...@@ -3113,8 +3103,7 @@ static int smiapp_probe(struct i2c_client *client, ...@@ -3113,8 +3103,7 @@ static int smiapp_probe(struct i2c_client *client,
smiapp_cleanup(sensor); smiapp_cleanup(sensor);
out_power_off: out_power_off:
pm_runtime_put(&client->dev); smiapp_power_off(&client->dev);
pm_runtime_disable(&client->dev);
return rval; return rval;
} }
...@@ -3127,8 +3116,10 @@ static int smiapp_remove(struct i2c_client *client) ...@@ -3127,8 +3116,10 @@ static int smiapp_remove(struct i2c_client *client)
v4l2_async_unregister_subdev(subdev); v4l2_async_unregister_subdev(subdev);
pm_runtime_suspend(&client->dev);
pm_runtime_disable(&client->dev); pm_runtime_disable(&client->dev);
if (!pm_runtime_status_suspended(&client->dev))
smiapp_power_off(&client->dev);
pm_runtime_set_suspended(&client->dev);
for (i = 0; i < sensor->ssds_used; i++) { for (i = 0; i < sensor->ssds_used; i++) {
v4l2_device_unregister_subdev(&sensor->ssds[i].sd); v4l2_device_unregister_subdev(&sensor->ssds[i].sd);
......
...@@ -291,8 +291,12 @@ static void tvp5150_selmux(struct v4l2_subdev *sd) ...@@ -291,8 +291,12 @@ static void tvp5150_selmux(struct v4l2_subdev *sd)
tvp5150_write(sd, TVP5150_OP_MODE_CTL, opmode); tvp5150_write(sd, TVP5150_OP_MODE_CTL, opmode);
tvp5150_write(sd, TVP5150_VD_IN_SRC_SEL_1, input); tvp5150_write(sd, TVP5150_VD_IN_SRC_SEL_1, input);
/* Svideo should enable YCrCb output and disable GPCL output /*
* For Composite and TV, it should be the reverse * Setup the FID/GLCO/VLK/HVLK and INTREQ/GPCL/VBLK output signals. For
* S-Video we output the vertical lock (VLK) signal on FID/GLCO/VLK/HVLK
* and set INTREQ/GPCL/VBLK to logic 0. For composite we output the
* field indicator (FID) signal on FID/GLCO/VLK/HVLK and set
* INTREQ/GPCL/VBLK to logic 1.
*/ */
val = tvp5150_read(sd, TVP5150_MISC_CTL); val = tvp5150_read(sd, TVP5150_MISC_CTL);
if (val < 0) { if (val < 0) {
...@@ -301,9 +305,9 @@ static void tvp5150_selmux(struct v4l2_subdev *sd) ...@@ -301,9 +305,9 @@ static void tvp5150_selmux(struct v4l2_subdev *sd)
} }
if (decoder->input == TVP5150_SVIDEO) if (decoder->input == TVP5150_SVIDEO)
val = (val & ~0x40) | 0x10; val = (val & ~TVP5150_MISC_CTL_GPCL) | TVP5150_MISC_CTL_HVLK;
else else
val = (val & ~0x10) | 0x40; val = (val & ~TVP5150_MISC_CTL_HVLK) | TVP5150_MISC_CTL_GPCL;
tvp5150_write(sd, TVP5150_MISC_CTL, val); tvp5150_write(sd, TVP5150_MISC_CTL, val);
}; };
...@@ -455,7 +459,12 @@ static const struct i2c_reg_value tvp5150_init_enable[] = { ...@@ -455,7 +459,12 @@ static const struct i2c_reg_value tvp5150_init_enable[] = {
},{ /* Automatic offset and AGC enabled */ },{ /* Automatic offset and AGC enabled */
TVP5150_ANAL_CHL_CTL, 0x15 TVP5150_ANAL_CHL_CTL, 0x15
},{ /* Activate YCrCb output 0x9 or 0xd ? */ },{ /* Activate YCrCb output 0x9 or 0xd ? */
TVP5150_MISC_CTL, 0x6f TVP5150_MISC_CTL, TVP5150_MISC_CTL_GPCL |
TVP5150_MISC_CTL_INTREQ_OE |
TVP5150_MISC_CTL_YCBCR_OE |
TVP5150_MISC_CTL_SYNC_OE |
TVP5150_MISC_CTL_VBLANK |
TVP5150_MISC_CTL_CLOCK_OE,
},{ /* Activates video std autodetection for all standards */ },{ /* Activates video std autodetection for all standards */
TVP5150_AUTOSW_MSK, 0x0 TVP5150_AUTOSW_MSK, 0x0
},{ /* Default format: 0x47. For 4:2:2: 0x40 */ },{ /* Default format: 0x47. For 4:2:2: 0x40 */
...@@ -861,8 +870,6 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd, ...@@ -861,8 +870,6 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
f = &format->format; f = &format->format;
tvp5150_reset(sd, 0);
f->width = decoder->rect.width; f->width = decoder->rect.width;
f->height = decoder->rect.height / 2; f->height = decoder->rect.height / 2;
...@@ -1051,21 +1058,27 @@ static const struct media_entity_operations tvp5150_sd_media_ops = { ...@@ -1051,21 +1058,27 @@ static const struct media_entity_operations tvp5150_sd_media_ops = {
static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
{ {
struct tvp5150 *decoder = to_tvp5150(sd); struct tvp5150 *decoder = to_tvp5150(sd);
/* Output format: 8-bit ITU-R BT.656 with embedded syncs */ int val;
int val = 0x09;
/* Output format: 8-bit 4:2:2 YUV with discrete sync */
if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
val = 0x0d;
/* Initializes TVP5150 to its default values */ /* Enable or disable the video output signals. */
/* # set PCLK (27MHz) */ val = tvp5150_read(sd, TVP5150_MISC_CTL);
tvp5150_write(sd, TVP5150_CONF_SHARED_PIN, 0x00); if (val < 0)
return val;
val &= ~(TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
TVP5150_MISC_CTL_CLOCK_OE);
if (enable) {
/*
* Enable the YCbCr and clock outputs. In discrete sync mode
* (non-BT.656) additionally enable the the sync outputs.
*/
val |= TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_CLOCK_OE;
if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
val |= TVP5150_MISC_CTL_SYNC_OE;
}
if (enable) tvp5150_write(sd, TVP5150_MISC_CTL, val);
tvp5150_write(sd, TVP5150_MISC_CTL, val);
else
tvp5150_write(sd, TVP5150_MISC_CTL, 0x00);
return 0; return 0;
} }
...@@ -1524,7 +1537,6 @@ static int tvp5150_probe(struct i2c_client *c, ...@@ -1524,7 +1537,6 @@ static int tvp5150_probe(struct i2c_client *c,
res = core->hdl.error; res = core->hdl.error;
goto err; goto err;
} }
v4l2_ctrl_handler_setup(&core->hdl);
/* Default is no cropping */ /* Default is no cropping */
core->rect.top = 0; core->rect.top = 0;
...@@ -1535,6 +1547,8 @@ static int tvp5150_probe(struct i2c_client *c, ...@@ -1535,6 +1547,8 @@ static int tvp5150_probe(struct i2c_client *c,
core->rect.left = 0; core->rect.left = 0;
core->rect.width = TVP5150_H_MAX; core->rect.width = TVP5150_H_MAX;
tvp5150_reset(sd, 0); /* Calls v4l2_ctrl_handler_setup() */
res = v4l2_async_register_subdev(sd); res = v4l2_async_register_subdev(sd);
if (res < 0) if (res < 0)
goto err; goto err;
......
...@@ -9,6 +9,15 @@ ...@@ -9,6 +9,15 @@
#define TVP5150_ANAL_CHL_CTL 0x01 /* Analog channel controls */ #define TVP5150_ANAL_CHL_CTL 0x01 /* Analog channel controls */
#define TVP5150_OP_MODE_CTL 0x02 /* Operation mode controls */ #define TVP5150_OP_MODE_CTL 0x02 /* Operation mode controls */
#define TVP5150_MISC_CTL 0x03 /* Miscellaneous controls */ #define TVP5150_MISC_CTL 0x03 /* Miscellaneous controls */
#define TVP5150_MISC_CTL_VBLK_GPCL BIT(7)
#define TVP5150_MISC_CTL_GPCL BIT(6)
#define TVP5150_MISC_CTL_INTREQ_OE BIT(5)
#define TVP5150_MISC_CTL_HVLK BIT(4)
#define TVP5150_MISC_CTL_YCBCR_OE BIT(3)
#define TVP5150_MISC_CTL_SYNC_OE BIT(2)
#define TVP5150_MISC_CTL_VBLANK BIT(1)
#define TVP5150_MISC_CTL_CLOCK_OE BIT(0)
#define TVP5150_AUTOSW_MSK 0x04 /* Autoswitch mask: TVP5150A / TVP5150AM */ #define TVP5150_AUTOSW_MSK 0x04 /* Autoswitch mask: TVP5150A / TVP5150AM */
/* Reserved 05h */ /* Reserved 05h */
......
...@@ -308,9 +308,7 @@ static void cobalt_pci_iounmap(struct cobalt *cobalt, struct pci_dev *pci_dev) ...@@ -308,9 +308,7 @@ static void cobalt_pci_iounmap(struct cobalt *cobalt, struct pci_dev *pci_dev)
static void cobalt_free_msi(struct cobalt *cobalt, struct pci_dev *pci_dev) static void cobalt_free_msi(struct cobalt *cobalt, struct pci_dev *pci_dev)
{ {
free_irq(pci_dev->irq, (void *)cobalt); free_irq(pci_dev->irq, (void *)cobalt);
pci_free_irq_vectors(pci_dev);
if (cobalt->msi_enabled)
pci_disable_msi(pci_dev);
} }
static int cobalt_setup_pci(struct cobalt *cobalt, struct pci_dev *pci_dev, static int cobalt_setup_pci(struct cobalt *cobalt, struct pci_dev *pci_dev,
...@@ -387,14 +385,12 @@ static int cobalt_setup_pci(struct cobalt *cobalt, struct pci_dev *pci_dev, ...@@ -387,14 +385,12 @@ static int cobalt_setup_pci(struct cobalt *cobalt, struct pci_dev *pci_dev,
from being generated. */ from being generated. */
cobalt_set_interrupt(cobalt, false); cobalt_set_interrupt(cobalt, false);
if (pci_enable_msi_range(pci_dev, 1, 1) < 1) { if (pci_alloc_irq_vectors(pci_dev, 1, 1, PCI_IRQ_MSI) < 1) {
cobalt_err("Could not enable MSI\n"); cobalt_err("Could not enable MSI\n");
cobalt->msi_enabled = false;
ret = -EIO; ret = -EIO;
goto err_release; goto err_release;
} }
msi_config_show(cobalt, pci_dev); msi_config_show(cobalt, pci_dev);
cobalt->msi_enabled = true;
/* Register IRQ */ /* Register IRQ */
if (request_irq(pci_dev->irq, cobalt_irq_handler, IRQF_SHARED, if (request_irq(pci_dev->irq, cobalt_irq_handler, IRQF_SHARED,
......
...@@ -287,8 +287,6 @@ struct cobalt { ...@@ -287,8 +287,6 @@ struct cobalt {
u32 irq_none; u32 irq_none;
u32 irq_full_fifo; u32 irq_full_fifo;
bool msi_enabled;
/* omnitek dma */ /* omnitek dma */
int dma_channels; int dma_channels;
int first_fifo_channel; int first_fifo_channel;
......
...@@ -97,14 +97,13 @@ struct pctv452e_state { ...@@ -97,14 +97,13 @@ struct pctv452e_state {
u8 c; /* transaction counter, wraps around... */ u8 c; /* transaction counter, wraps around... */
u8 initialized; /* set to 1 if 0x15 has been sent */ u8 initialized; /* set to 1 if 0x15 has been sent */
u16 last_rc_key; u16 last_rc_key;
unsigned char data[80];
}; };
static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
unsigned int write_len, unsigned int read_len) unsigned int write_len, unsigned int read_len)
{ {
struct pctv452e_state *state = (struct pctv452e_state *)d->priv; struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
u8 *buf;
u8 id; u8 id;
unsigned int rlen; unsigned int rlen;
int ret; int ret;
...@@ -114,36 +113,39 @@ static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, ...@@ -114,36 +113,39 @@ static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
return -EIO; return -EIO;
} }
mutex_lock(&state->ca_mutex); buf = kmalloc(64, GFP_KERNEL);
if (!buf)
return -ENOMEM;
id = state->c++; id = state->c++;
state->data[0] = SYNC_BYTE_OUT; buf[0] = SYNC_BYTE_OUT;
state->data[1] = id; buf[1] = id;
state->data[2] = cmd; buf[2] = cmd;
state->data[3] = write_len; buf[3] = write_len;
memcpy(state->data + 4, data, write_len); memcpy(buf + 4, data, write_len);
rlen = (read_len > 0) ? 64 : 0; rlen = (read_len > 0) ? 64 : 0;
ret = dvb_usb_generic_rw(d, state->data, 4 + write_len, ret = dvb_usb_generic_rw(d, buf, 4 + write_len,
state->data, rlen, /* delay_ms */ 0); buf, rlen, /* delay_ms */ 0);
if (0 != ret) if (0 != ret)
goto failed; goto failed;
ret = -EIO; ret = -EIO;
if (SYNC_BYTE_IN != state->data[0] || id != state->data[1]) if (SYNC_BYTE_IN != buf[0] || id != buf[1])
goto failed; goto failed;
memcpy(data, state->data + 4, read_len); memcpy(data, buf + 4, read_len);
mutex_unlock(&state->ca_mutex); kfree(buf);
return 0; return 0;
failed: failed:
err("CI error %d; %02X %02X %02X -> %*ph.", err("CI error %d; %02X %02X %02X -> %*ph.",
ret, SYNC_BYTE_OUT, id, cmd, 3, state->data); ret, SYNC_BYTE_OUT, id, cmd, 3, buf);
mutex_unlock(&state->ca_mutex); kfree(buf);
return ret; return ret;
} }
...@@ -410,53 +412,57 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr, ...@@ -410,53 +412,57 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr,
u8 *rcv_buf, u8 rcv_len) u8 *rcv_buf, u8 rcv_len)
{ {
struct pctv452e_state *state = (struct pctv452e_state *)d->priv; struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
u8 *buf;
u8 id; u8 id;
int ret; int ret;
mutex_lock(&state->ca_mutex); buf = kmalloc(64, GFP_KERNEL);
if (!buf)
return -ENOMEM;
id = state->c++; id = state->c++;
ret = -EINVAL; ret = -EINVAL;
if (snd_len > 64 - 7 || rcv_len > 64 - 7) if (snd_len > 64 - 7 || rcv_len > 64 - 7)
goto failed; goto failed;
state->data[0] = SYNC_BYTE_OUT; buf[0] = SYNC_BYTE_OUT;
state->data[1] = id; buf[1] = id;
state->data[2] = PCTV_CMD_I2C; buf[2] = PCTV_CMD_I2C;
state->data[3] = snd_len + 3; buf[3] = snd_len + 3;
state->data[4] = addr << 1; buf[4] = addr << 1;
state->data[5] = snd_len; buf[5] = snd_len;
state->data[6] = rcv_len; buf[6] = rcv_len;
memcpy(state->data + 7, snd_buf, snd_len); memcpy(buf + 7, snd_buf, snd_len);
ret = dvb_usb_generic_rw(d, state->data, 7 + snd_len, ret = dvb_usb_generic_rw(d, buf, 7 + snd_len,
state->data, /* rcv_len */ 64, buf, /* rcv_len */ 64,
/* delay_ms */ 0); /* delay_ms */ 0);
if (ret < 0) if (ret < 0)
goto failed; goto failed;
/* TT USB protocol error. */ /* TT USB protocol error. */
ret = -EIO; ret = -EIO;
if (SYNC_BYTE_IN != state->data[0] || id != state->data[1]) if (SYNC_BYTE_IN != buf[0] || id != buf[1])
goto failed; goto failed;
/* I2C device didn't respond as expected. */ /* I2C device didn't respond as expected. */
ret = -EREMOTEIO; ret = -EREMOTEIO;
if (state->data[5] < snd_len || state->data[6] < rcv_len) if (buf[5] < snd_len || buf[6] < rcv_len)
goto failed; goto failed;
memcpy(rcv_buf, state->data + 7, rcv_len); memcpy(rcv_buf, buf + 7, rcv_len);
mutex_unlock(&state->ca_mutex);
kfree(buf);
return rcv_len; return rcv_len;
failed: failed:
err("I2C error %d; %02X %02X %02X %02X %02X -> %*ph", err("I2C error %d; %02X %02X %02X %02X %02X -> %*ph",
ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len, ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len,
7, state->data); 7, buf);
mutex_unlock(&state->ca_mutex); kfree(buf);
return ret; return ret;
} }
...@@ -505,7 +511,7 @@ static u32 pctv452e_i2c_func(struct i2c_adapter *adapter) ...@@ -505,7 +511,7 @@ static u32 pctv452e_i2c_func(struct i2c_adapter *adapter)
static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
{ {
struct pctv452e_state *state = (struct pctv452e_state *)d->priv; struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
u8 *rx; u8 *b0, *rx;
int ret; int ret;
info("%s: %d\n", __func__, i); info("%s: %d\n", __func__, i);
...@@ -516,11 +522,12 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) ...@@ -516,11 +522,12 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
if (state->initialized) if (state->initialized)
return 0; return 0;
rx = kmalloc(PCTV_ANSWER_LEN, GFP_KERNEL); b0 = kmalloc(5 + PCTV_ANSWER_LEN, GFP_KERNEL);
if (!rx) if (!b0)
return -ENOMEM; return -ENOMEM;
mutex_lock(&state->ca_mutex); rx = b0 + 5;
/* hmm where shoud this should go? */ /* hmm where shoud this should go? */
ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE); ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE);
if (ret != 0) if (ret != 0)
...@@ -528,66 +535,70 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) ...@@ -528,66 +535,70 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
__func__, ret); __func__, ret);
/* this is a one-time initialization, dont know where to put */ /* this is a one-time initialization, dont know where to put */
state->data[0] = 0xaa; b0[0] = 0xaa;
state->data[1] = state->c++; b0[1] = state->c++;
state->data[2] = PCTV_CMD_RESET; b0[2] = PCTV_CMD_RESET;
state->data[3] = 1; b0[3] = 1;
state->data[4] = 0; b0[4] = 0;
/* reset board */ /* reset board */
ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0); ret = dvb_usb_generic_rw(d, b0, 5, rx, PCTV_ANSWER_LEN, 0);
if (ret) if (ret)
goto ret; goto ret;
state->data[1] = state->c++; b0[1] = state->c++;
state->data[4] = 1; b0[4] = 1;
/* reset board (again?) */ /* reset board (again?) */
ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0); ret = dvb_usb_generic_rw(d, b0, 5, rx, PCTV_ANSWER_LEN, 0);
if (ret) if (ret)
goto ret; goto ret;
state->initialized = 1; state->initialized = 1;
ret: ret:
mutex_unlock(&state->ca_mutex); kfree(b0);
kfree(rx);
return ret; return ret;
} }
static int pctv452e_rc_query(struct dvb_usb_device *d) static int pctv452e_rc_query(struct dvb_usb_device *d)
{ {
struct pctv452e_state *state = (struct pctv452e_state *)d->priv; struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
u8 *b, *rx;
int ret, i; int ret, i;
u8 id; u8 id;
mutex_lock(&state->ca_mutex); b = kmalloc(CMD_BUFFER_SIZE + PCTV_ANSWER_LEN, GFP_KERNEL);
if (!b)
return -ENOMEM;
rx = b + CMD_BUFFER_SIZE;
id = state->c++; id = state->c++;
/* prepare command header */ /* prepare command header */
state->data[0] = SYNC_BYTE_OUT; b[0] = SYNC_BYTE_OUT;
state->data[1] = id; b[1] = id;
state->data[2] = PCTV_CMD_IR; b[2] = PCTV_CMD_IR;
state->data[3] = 0; b[3] = 0;
/* send ir request */ /* send ir request */
ret = dvb_usb_generic_rw(d, state->data, 4, ret = dvb_usb_generic_rw(d, b, 4, rx, PCTV_ANSWER_LEN, 0);
state->data, PCTV_ANSWER_LEN, 0);
if (ret != 0) if (ret != 0)
goto ret; goto ret;
if (debug > 3) { if (debug > 3) {
info("%s: read: %2d: %*ph: ", __func__, ret, 3, state->data); info("%s: read: %2d: %*ph: ", __func__, ret, 3, rx);
for (i = 0; (i < state->data[3]) && ((i + 3) < PCTV_ANSWER_LEN); i++) for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++)
info(" %02x", state->data[i + 3]); info(" %02x", rx[i+3]);
info("\n"); info("\n");
} }
if ((state->data[3] == 9) && (state->data[12] & 0x01)) { if ((rx[3] == 9) && (rx[12] & 0x01)) {
/* got a "press" event */ /* got a "press" event */
state->last_rc_key = RC_SCANCODE_RC5(state->data[7], state->data[6]); state->last_rc_key = RC_SCANCODE_RC5(rx[7], rx[6]);
if (debug > 2) if (debug > 2)
info("%s: cmd=0x%02x sys=0x%02x\n", info("%s: cmd=0x%02x sys=0x%02x\n",
__func__, state->data[6], state->data[7]); __func__, rx[6], rx[7]);
rc_keydown(d->rc_dev, RC_TYPE_RC5, state->last_rc_key, 0); rc_keydown(d->rc_dev, RC_TYPE_RC5, state->last_rc_key, 0);
} else if (state->last_rc_key) { } else if (state->last_rc_key) {
...@@ -595,7 +606,7 @@ static int pctv452e_rc_query(struct dvb_usb_device *d) ...@@ -595,7 +606,7 @@ static int pctv452e_rc_query(struct dvb_usb_device *d)
state->last_rc_key = 0; state->last_rc_key = 0;
} }
ret: ret:
mutex_unlock(&state->ca_mutex); kfree(b);
return ret; return ret;
} }
......
...@@ -1665,14 +1665,15 @@ static inline void cec_msg_report_current_latency(struct cec_msg *msg, ...@@ -1665,14 +1665,15 @@ static inline void cec_msg_report_current_latency(struct cec_msg *msg,
__u8 audio_out_compensated, __u8 audio_out_compensated,
__u8 audio_out_delay) __u8 audio_out_delay)
{ {
msg->len = 7; msg->len = 6;
msg->msg[0] |= 0xf; /* broadcast */ msg->msg[0] |= 0xf; /* broadcast */
msg->msg[1] = CEC_MSG_REPORT_CURRENT_LATENCY; msg->msg[1] = CEC_MSG_REPORT_CURRENT_LATENCY;
msg->msg[2] = phys_addr >> 8; msg->msg[2] = phys_addr >> 8;
msg->msg[3] = phys_addr & 0xff; msg->msg[3] = phys_addr & 0xff;
msg->msg[4] = video_latency; msg->msg[4] = video_latency;
msg->msg[5] = (low_latency_mode << 2) | audio_out_compensated; msg->msg[5] = (low_latency_mode << 2) | audio_out_compensated;
msg->msg[6] = audio_out_delay; if (audio_out_compensated == 3)
msg->msg[msg->len++] = audio_out_delay;
} }
static inline void cec_ops_report_current_latency(const struct cec_msg *msg, static inline void cec_ops_report_current_latency(const struct cec_msg *msg,
...@@ -1686,7 +1687,10 @@ static inline void cec_ops_report_current_latency(const struct cec_msg *msg, ...@@ -1686,7 +1687,10 @@ static inline void cec_ops_report_current_latency(const struct cec_msg *msg,
*video_latency = msg->msg[4]; *video_latency = msg->msg[4];
*low_latency_mode = (msg->msg[5] >> 2) & 1; *low_latency_mode = (msg->msg[5] >> 2) & 1;
*audio_out_compensated = msg->msg[5] & 3; *audio_out_compensated = msg->msg[5] & 3;
*audio_out_delay = msg->msg[6]; if (*audio_out_compensated == 3 && msg->len >= 7)
*audio_out_delay = msg->msg[6];
else
*audio_out_delay = 0;
} }
static inline void cec_msg_request_current_latency(struct cec_msg *msg, static inline void cec_msg_request_current_latency(struct cec_msg *msg,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment