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:
 - removal of sn9c102.  This device driver was replaced a long time ago
   by gspca
 - solo6x10 and go7007 webcam drivers moved from staging into
   mainstream.  They were waiting for an API to allow setting the image
   detection matrix
 - SDR drivers moved from staging into mainstream: sdr-msi3101 (renamed
   as msi2500) and rtl2832
 - added SDR driver for airspy
 - added demux driver: si2165
 - rework at several RC subsystem, making the code for RC-5 SZ variant
   to be added at the standard RC5 decoder
 - added decoder for the XMP IR protocol
 - tuner driver moved from staging into mainstream: msi3101 (renamed as
   msi001)
 - added documentation for some additional SDR pixfmt
 - some device tree bindings documented
 - added support for exynos3250 at s5p-jpeg
 - remove the obsolete, unmaintained and broken mx1_camera driver
 - added support for remote controllers at au0828 driver
 - added a RC driver: sunxi-cir
 - several driver fixes, enhancements and cleanups.

* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (455 commits)
  [media] cx23885: fix UNSET/TUNER_ABSENT confusion
  [media] coda: fix build error by making reset control optional
  [media] radio-miropcm20: fix sparse NULL pointer warning
  [media] MAINTAINERS: Update go7007 pattern
  [media] MAINTAINERS: Update solo6x10 patterns
  [media] media: atmel-isi: add primary DT support
  [media] media: atmel-isi: convert the pdata from pointer to structure
  [media] media: atmel-isi: add v4l2 async probe support
  [media] rcar_vin: add devicetree support
  [media] media: pxa_camera device-tree support
  [media] media: mt9m111: add device-tree suppport
  [media] soc_camera: add support for dt binding soc_camera drivers
  [media] media: soc_camera: pxa_camera documentation device-tree support
  [media] media: mt9m111: add device-tree documentation
  [media] s5p-mfc: remove unnecessary calling to function video_devdata()
  [media] s5p-jpeg: add chroma subsampling adjustment for Exynos3250
  [media] s5p-jpeg: Prevent erroneous downscaling for Exynos3250 SoC
  [media] s5p-jpeg: Assure proper crop rectangle initialization
  [media] s5p-jpeg: fix g_selection op
  [media] s5p-jpeg: Adjust jpeg_bound_align_image to Exynos3250 needs
  ...
This commit is contained in:
Linus Torvalds 2014-08-05 16:36:30 -07:00
commit f4d33337ea
442 changed files with 16105 additions and 17004 deletions

View file

@ -59,6 +59,13 @@ config MEDIA_RADIO_SUPPORT
support radio reception. Disabling this option will
disable support for them.
config MEDIA_SDR_SUPPORT
bool "Software defined radio support"
---help---
Enable software defined radio support.
Say Y when you have a software defined radio device.
config MEDIA_RC_SUPPORT
bool "Remote Controller support"
depends on INPUT
@ -95,7 +102,7 @@ config MEDIA_CONTROLLER
config VIDEO_DEV
tristate
depends on MEDIA_SUPPORT
depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT
depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT || MEDIA_SDR_SUPPORT
default y
config VIDEO_V4L2_SUBDEV_API
@ -171,10 +178,11 @@ comment "Media ancillary drivers (tuners, sensors, i2c, frontends)"
config MEDIA_SUBDRV_AUTOSELECT
bool "Autoselect ancillary drivers (tuners, sensors, i2c, frontends)"
depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_CAMERA_SUPPORT
depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_CAMERA_SUPPORT || MEDIA_SDR_SUPPORT
depends on HAS_IOMEM
select I2C
select I2C_MUX
select SPI
default y
help
By default, a media driver auto-selects all possible ancillary

View file

@ -533,13 +533,12 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
saa7146_vbi_uops.init(dev,vv);
fmt = &vv->ov_fb.fmt;
fmt->width = vv->standard->h_max_out;
fmt->height = vv->standard->v_max_out;
fmt->pixelformat = V4L2_PIX_FMT_RGB565;
fmt->bytesperline = 2 * fmt->width;
fmt->sizeimage = fmt->bytesperline * fmt->height;
fmt->colorspace = V4L2_COLORSPACE_SRGB;
vv->ov_fb.fmt.width = vv->standard->h_max_out;
vv->ov_fb.fmt.height = vv->standard->v_max_out;
vv->ov_fb.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
vv->ov_fb.fmt.bytesperline = 2 * vv->ov_fb.fmt.width;
vv->ov_fb.fmt.sizeimage = vv->ov_fb.fmt.bytesperline * vv->ov_fb.fmt.height;
vv->ov_fb.fmt.colorspace = V4L2_COLORSPACE_SRGB;
fmt = &vv->video_fmt;
fmt->width = 384;
@ -613,7 +612,6 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
vfd->lock = &dev->v4l2_lock;
vfd->v4l2_dev = &dev->v4l2_dev;
vfd->tvnorms = 0;
set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
for (i = 0; i < dev->ext_vv_data->num_stds; i++)
vfd->tvnorms |= dev->ext_vv_data->stds[i].id;
strlcpy(vfd->name, name, sizeof(vfd->name));

View file

@ -22,8 +22,7 @@ config SMS_SIANO_DEBUGFS
bool "Enable debugfs for smsdvb"
depends on SMS_SIANO_MDTV
depends on DEBUG_FS
depends on SMS_USB_DRV
depends on CONFIG_SMS_USB_DRV = CONFIG_SMS_SDIO_DRV
depends on SMS_USB_DRV = SMS_SDIO_DRV
---help---
Choose Y to enable visualizing a dump of the frontend

View file

@ -88,7 +88,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
dev->priv = coredev;
dev->driver_type = RC_DRIVER_IR_RAW;
rc_set_allowed_protocols(dev, RC_BIT_ALL);
dev->allowed_protocols = RC_BIT_ALL;
dev->map_name = sms_get_board(board_id)->rc_codes;
dev->driver_name = MODULE_NAME;

View file

@ -244,6 +244,7 @@
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
#define USB_PID_TECHNOTREND_CONNECT_S2400_8KEEPROM 0x3009
#define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d
#define USB_PID_TECHNOTREND_TVSTICK_CT2_4400 0x3014
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058
@ -363,6 +364,7 @@
#define USB_PID_TVWAY_PLUS 0x0002
#define USB_PID_SVEON_STV20 0xe39d
#define USB_PID_SVEON_STV20_RTL2832U 0xd39d
#define USB_PID_SVEON_STV21 0xd3b0
#define USB_PID_SVEON_STV22 0xe401
#define USB_PID_SVEON_STV22_IT9137 0xe411
#define USB_PID_AZUREWAVE_AZ6027 0x3275

View file

@ -96,10 +96,6 @@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open(
* FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again.
*/
#define DVB_FE_NO_EXIT 0
#define DVB_FE_NORMAL_EXIT 1
#define DVB_FE_DEVICE_REMOVED 2
static DEFINE_MUTEX(frontend_mutex);
struct dvb_frontend_private {
@ -113,7 +109,6 @@ struct dvb_frontend_private {
wait_queue_head_t wait_queue;
struct task_struct *thread;
unsigned long release_jiffies;
unsigned int exit;
unsigned int wakeup;
fe_status_t status;
unsigned long tune_mode_flags;
@ -565,7 +560,7 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
if (fepriv->exit != DVB_FE_NO_EXIT)
if (fe->exit != DVB_FE_NO_EXIT)
return 1;
if (fepriv->dvbdev->writers == 1)
@ -629,7 +624,7 @@ restart:
/* got signal or quitting */
if (!down_interruptible(&fepriv->sem))
semheld = true;
fepriv->exit = DVB_FE_NORMAL_EXIT;
fe->exit = DVB_FE_NORMAL_EXIT;
break;
}
@ -739,9 +734,9 @@ restart:
fepriv->thread = NULL;
if (kthread_should_stop())
fepriv->exit = DVB_FE_DEVICE_REMOVED;
fe->exit = DVB_FE_DEVICE_REMOVED;
else
fepriv->exit = DVB_FE_NO_EXIT;
fe->exit = DVB_FE_NO_EXIT;
mb();
if (semheld)
@ -756,7 +751,8 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
dev_dbg(fe->dvb->device, "%s:\n", __func__);
fepriv->exit = DVB_FE_NORMAL_EXIT;
if (fe->exit != DVB_FE_DEVICE_REMOVED)
fe->exit = DVB_FE_NORMAL_EXIT;
mb();
if (!fepriv->thread)
@ -826,7 +822,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
dev_dbg(fe->dvb->device, "%s:\n", __func__);
if (fepriv->thread) {
if (fepriv->exit == DVB_FE_NO_EXIT)
if (fe->exit == DVB_FE_NO_EXIT)
return 0;
else
dvb_frontend_stop (fe);
@ -838,7 +834,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
return -EINTR;
fepriv->state = FESTATE_IDLE;
fepriv->exit = DVB_FE_NO_EXIT;
fe->exit = DVB_FE_NO_EXIT;
fepriv->thread = NULL;
mb();
@ -1906,7 +1902,7 @@ static int dvb_frontend_ioctl(struct file *file,
if (down_interruptible(&fepriv->sem))
return -ERESTARTSYS;
if (fepriv->exit != DVB_FE_NO_EXIT) {
if (fe->exit != DVB_FE_NO_EXIT) {
up(&fepriv->sem);
return -ENODEV;
}
@ -2424,7 +2420,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
int ret;
dev_dbg(fe->dvb->device, "%s:\n", __func__);
if (fepriv->exit == DVB_FE_DEVICE_REMOVED)
if (fe->exit == DVB_FE_DEVICE_REMOVED)
return -ENODEV;
if (adapter->mfe_shared) {
@ -2529,7 +2525,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
if (dvbdev->users == -1) {
wake_up(&fepriv->wait_queue);
if (fepriv->exit != DVB_FE_NO_EXIT)
if (fe->exit != DVB_FE_NO_EXIT)
wake_up(&dvbdev->wait_queue);
if (fe->ops.ts_bus_ctrl)
fe->ops.ts_bus_ctrl(fe, 0);
@ -2572,12 +2568,14 @@ int dvb_frontend_resume(struct dvb_frontend *fe)
dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
fe->id);
fe->exit = DVB_FE_DEVICE_RESUME;
if (fe->ops.init)
ret = fe->ops.init(fe);
if (fe->ops.tuner_ops.init)
ret = fe->ops.tuner_ops.init(fe);
fe->exit = DVB_FE_NO_EXIT;
fepriv->state = FESTATE_RETUNE;
dvb_frontend_wakeup(fe);
@ -2666,20 +2664,20 @@ void dvb_frontend_detach(struct dvb_frontend* fe)
if (fe->ops.release_sec) {
fe->ops.release_sec(fe);
symbol_put_addr(fe->ops.release_sec);
dvb_detach(fe->ops.release_sec);
}
if (fe->ops.tuner_ops.release) {
fe->ops.tuner_ops.release(fe);
symbol_put_addr(fe->ops.tuner_ops.release);
dvb_detach(fe->ops.tuner_ops.release);
}
if (fe->ops.analog_ops.release) {
fe->ops.analog_ops.release(fe);
symbol_put_addr(fe->ops.analog_ops.release);
dvb_detach(fe->ops.analog_ops.release);
}
ptr = (void*)fe->ops.release;
if (ptr) {
fe->ops.release(fe);
symbol_put_addr(ptr);
dvb_detach(ptr);
}
}
#else

View file

@ -405,6 +405,11 @@ struct dtv_frontend_properties {
struct dtv_fe_stats block_count;
};
#define DVB_FE_NO_EXIT 0
#define DVB_FE_NORMAL_EXIT 1
#define DVB_FE_DEVICE_REMOVED 2
#define DVB_FE_DEVICE_RESUME 3
struct dvb_frontend {
struct dvb_frontend_ops ops;
struct dvb_adapter *dvb;
@ -418,6 +423,7 @@ struct dvb_frontend {
#define DVB_FRONTEND_COMPONENT_DEMOD 1
int (*callback)(void *adapter_priv, int component, int cmd, int arg);
int id;
unsigned int exit;
};
extern int dvb_register_frontend(struct dvb_adapter *dvb,

View file

@ -136,11 +136,15 @@ extern int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
__r; \
})
#define dvb_detach(FUNC) symbol_put_addr(FUNC)
#else
#define dvb_attach(FUNCTION, ARGS...) ({ \
FUNCTION(ARGS); \
})
#define dvb_detach(FUNC) {}
#endif
#endif /* #ifndef _DVBDEV_H_ */

View file

@ -63,6 +63,15 @@ config DVB_TDA18271C2DD
Say Y when you want to support this tuner.
config DVB_SI2165
tristate "Silicon Labs si2165 based"
depends on DVB_CORE && I2C
default m if !MEDIA_SUBDRV_AUTOSELECT
help
A DVB-C/T demodulator.
Say Y when you want to support this frontend.
comment "DVB-S (satellite) frontends"
depends on DVB_CORE
@ -446,6 +455,15 @@ config DVB_RTL2832
help
Say Y when you want to support this frontend.
config DVB_RTL2832_SDR
tristate "Realtek RTL2832 SDR"
depends on DVB_CORE && I2C && I2C_MUX && VIDEO_V4L2 && MEDIA_SDR_SUPPORT && USB
select DVB_RTL2832
select VIDEOBUF2_VMALLOC
default m if !MEDIA_SUBDRV_AUTOSELECT
help
Say Y when you want to support this SDR module.
config DVB_SI2168
tristate "Silicon Labs Si2168"
depends on DVB_CORE && I2C && I2C_MUX

View file

@ -5,6 +5,11 @@
ccflags-y += -I$(srctree)/drivers/media/dvb-core/
ccflags-y += -I$(srctree)/drivers/media/tuners/
# FIXME: RTL2832 SDR driver uses power management directly from USB IF driver
ifdef CONFIG_DVB_RTL2832_SDR
ccflags-y += -I$(srctree)/drivers/media/usb/dvb-usb-v2
endif
stb0899-objs := stb0899_drv.o stb0899_algo.o
stv0900-objs := stv0900_core.o stv0900_sw.o
drxd-objs := drxd_firm.o drxd_hard.o
@ -100,10 +105,12 @@ obj-$(CONFIG_DVB_STV0367) += stv0367.o
obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
obj-$(CONFIG_DVB_DRXK) += drxk.o
obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
obj-$(CONFIG_DVB_SI2165) += si2165.o
obj-$(CONFIG_DVB_A8293) += a8293.o
obj-$(CONFIG_DVB_TDA10071) += tda10071.o
obj-$(CONFIG_DVB_RTL2830) += rtl2830.o
obj-$(CONFIG_DVB_RTL2832) += rtl2832.o
obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o
obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
obj-$(CONFIG_DVB_AF9033) += af9033.o

View file

@ -470,7 +470,6 @@ static int af9013_statistics_snr_result(struct dvb_frontend *fe)
break;
default:
goto err;
break;
}
for (i = 0; i < len; i++) {

View file

@ -220,7 +220,7 @@ static void setup_vbi(struct au8522_state *state, int aud_input)
}
static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
static void setup_decoder_defaults(struct au8522_state *state, bool is_svideo)
{
int i;
int filter_coef_type;
@ -237,13 +237,10 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
/* Other decoder registers */
au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
if (input_mode == 0x23) {
/* S-Video input mapping */
if (is_svideo)
au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04);
} else {
/* All other modes (CVBS/ATVRF etc.) */
else
au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00);
}
au8522_writereg(state, AU8522_TVDEC_PGA_REG012H,
AU8522_TVDEC_PGA_REG012H_CVBS);
@ -251,12 +248,23 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
AU8522_TVDEC_COMB_MODE_REG015H_CVBS);
au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H,
AU8522_TVDED_DBG_MODE_REG060H_CVBS);
au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 |
AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_MN);
au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC);
if (state->std == V4L2_STD_PAL_M) {
au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 |
AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_AUTO);
au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_PAL_M);
} else {
/* NTSC */
au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 |
AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_MN);
au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC);
}
au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H,
AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS);
au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H,
@ -275,8 +283,7 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH,
AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS);
if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
if (is_svideo) {
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO);
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
@ -317,8 +324,7 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
setup_vbi(state, 0);
if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
if (is_svideo) {
/* Despite what the table says, for the HVR-950q we still need
to be in CVBS mode for the S-Video input (reason unknown). */
/* filter_coef_type = 3; */
@ -346,7 +352,7 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
au8522_writereg(state, AU8522_REG436H, 0x3c);
}
static void au8522_setup_cvbs_mode(struct au8522_state *state)
static void au8522_setup_cvbs_mode(struct au8522_state *state, u8 input_mode)
{
/* here we're going to try the pre-programmed route */
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
@ -358,16 +364,16 @@ static void au8522_setup_cvbs_mode(struct au8522_state *state)
/* Enable clamping control */
au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, input_mode);
setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
setup_decoder_defaults(state, false);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
}
static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state,
u8 input_mode)
{
/* here we're going to try the pre-programmed route */
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
@ -384,24 +390,22 @@ static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
/* Set input mode to CVBS on channel 4 with SIF audio input enabled */
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, input_mode);
setup_decoder_defaults(state,
AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
setup_decoder_defaults(state, false);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
}
static void au8522_setup_svideo_mode(struct au8522_state *state)
static void au8522_setup_svideo_mode(struct au8522_state *state,
u8 input_mode)
{
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO);
/* Set input to Y on Channe1, C on Channel 3 */
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, input_mode);
/* PGA in automatic mode */
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
@ -409,8 +413,7 @@ static void au8522_setup_svideo_mode(struct au8522_state *state)
/* Enable clamping control */
au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
setup_decoder_defaults(state,
AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
setup_decoder_defaults(state, true);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
@ -432,8 +435,9 @@ static void disable_audio_input(struct au8522_state *state)
}
/* 0=disable, 1=SIF */
static void set_audio_input(struct au8522_state *state, int aud_input)
static void set_audio_input(struct au8522_state *state)
{
int aud_input = state->aud_input;
int i;
/* Note that this function needs to be used in conjunction with setting
@ -465,8 +469,9 @@ static void set_audio_input(struct au8522_state *state, int aud_input)
au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
msleep(150);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00);
msleep(1);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d);
msleep(10);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
msleep(50);
au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
@ -539,58 +544,109 @@ static int au8522_s_register(struct v4l2_subdev *sd,
}
#endif
static void au8522_video_set(struct au8522_state *state)
{
u8 input_mode;
au8522_writereg(state, 0xa4, 1 << 5);
switch (state->vid_input) {
case AU8522_COMPOSITE_CH1:
input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH1;
au8522_setup_cvbs_mode(state, input_mode);
break;
case AU8522_COMPOSITE_CH2:
input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH2;
au8522_setup_cvbs_mode(state, input_mode);
break;
case AU8522_COMPOSITE_CH3:
input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH3;
au8522_setup_cvbs_mode(state, input_mode);
break;
case AU8522_COMPOSITE_CH4:
input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH4;
au8522_setup_cvbs_mode(state, input_mode);
break;
case AU8522_SVIDEO_CH13:
input_mode = AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13;
au8522_setup_svideo_mode(state, input_mode);
break;
case AU8522_SVIDEO_CH24:
input_mode = AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24;
au8522_setup_svideo_mode(state, input_mode);
break;
default:
case AU8522_COMPOSITE_CH4_SIF:
input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF;
au8522_setup_cvbs_tuner_mode(state, input_mode);
break;
}
}
static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
{
struct au8522_state *state = to_state(sd);
if (enable) {
/*
* Clear out any state associated with the digital side of the
* chip, so that when it gets powered back up it won't think
* that it is already tuned
*/
state->current_frequency = 0;
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
0x01);
msleep(1);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
msleep(10);
au8522_video_set(state);
set_audio_input(state);
state->operational_mode = AU8522_ANALOG_MODE;
} else {
/* This does not completely power down the device
(it only reduces it from around 140ma to 80ma) */
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
1 << 5);
state->operational_mode = AU8522_SUSPEND_MODE;
}
return 0;
}
static int au8522_reset(struct v4l2_subdev *sd, u32 val)
{
struct au8522_state *state = to_state(sd);
state->operational_mode = AU8522_ANALOG_MODE;
/* Clear out any state associated with the digital side of the
chip, so that when it gets powered back up it won't think
that it is already tuned */
state->current_frequency = 0;
au8522_writereg(state, 0xa4, 1 << 5);
return 0;
}
static int au8522_s_video_routing(struct v4l2_subdev *sd,
u32 input, u32 output, u32 config)
{
struct au8522_state *state = to_state(sd);
au8522_reset(sd, 0);
if (input == AU8522_COMPOSITE_CH1) {
au8522_setup_cvbs_mode(state);
} else if (input == AU8522_SVIDEO_CH13) {
au8522_setup_svideo_mode(state);
} else if (input == AU8522_COMPOSITE_CH4_SIF) {
au8522_setup_cvbs_tuner_mode(state);
} else {
switch(input) {
case AU8522_COMPOSITE_CH1:
case AU8522_SVIDEO_CH13:
case AU8522_COMPOSITE_CH4_SIF:
state->vid_input = input;
break;
default:
printk(KERN_ERR "au8522 mode not currently supported\n");
return -EINVAL;
}
if (state->operational_mode == AU8522_ANALOG_MODE)
au8522_video_set(state);
return 0;
}
static int au8522_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
{
struct au8522_state *state = to_state(sd);
if ((std & (V4L2_STD_PAL_M | V4L2_STD_NTSC_M)) == 0)
return -EINVAL;
state->std = std;
if (state->operational_mode == AU8522_ANALOG_MODE)
au8522_video_set(state);
return 0;
}
@ -598,7 +654,12 @@ static int au8522_s_audio_routing(struct v4l2_subdev *sd,
u32 input, u32 output, u32 config)
{
struct au8522_state *state = to_state(sd);
set_audio_input(state, input);
state->aud_input = input;
if (state->operational_mode == AU8522_ANALOG_MODE)
set_audio_input(state);
return 0;
}
@ -629,7 +690,6 @@ static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
static const struct v4l2_subdev_core_ops au8522_core_ops = {
.log_status = v4l2_ctrl_subdev_log_status,
.reset = au8522_reset,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = au8522_g_register,
.s_register = au8522_s_register,
@ -647,6 +707,7 @@ static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
static const struct v4l2_subdev_video_ops au8522_video_ops = {
.s_routing = au8522_s_video_routing,
.s_stream = au8522_s_stream,
.s_std = au8522_s_std,
};
static const struct v4l2_subdev_ops au8522_ops = {
@ -729,6 +790,7 @@ static int au8522_probe(struct i2c_client *client,
}
state->c = client;
state->std = V4L2_STD_NTSC_M;
state->vid_input = AU8522_COMPOSITE_CH1;
state->aud_input = AU8522_AUDIO_NONE;
state->id = 8522;

View file

@ -37,6 +37,7 @@
#define AU8522_ANALOG_MODE 0
#define AU8522_DIGITAL_MODE 1
#define AU8522_SUSPEND_MODE 2
struct au8522_state {
struct i2c_client *c;
@ -347,6 +348,7 @@ int au8522_led_ctrl(struct au8522_state *state, int led);
/* Format control 2 */
#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_AUTODETECT 0x00
#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC 0x01
#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_PAL_M 0x02
#define AU8522_INPUT_CONTROL_REG081H_ATSC 0xC4

View file

@ -52,6 +52,12 @@ struct cxd2820r_config {
*/
u8 ts_mode;
/* TS clock inverted.
* Default: 0
* Values: 0, 1
*/
bool ts_clock_inv;
/* IF AGC polarity.
* Default: 0
* Values: 0, 1

View file

@ -45,6 +45,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
{ 0x1008b, 0x07, 0xff },
{ 0x1001f, priv->cfg.if_agc_polarity << 7, 0x80 },
{ 0x10070, priv->cfg.ts_mode, 0xff },
{ 0x10071, !priv->cfg.ts_clock_inv << 4, 0x10 },
};
dev_dbg(&priv->i2c->dev, "%s: frequency=%d symbol_rate=%d\n", __func__,

View file

@ -46,6 +46,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
{ 0x00088, 0x01, 0xff },
{ 0x00070, priv->cfg.ts_mode, 0xff },
{ 0x00071, !priv->cfg.ts_clock_inv << 4, 0x10 },
{ 0x000cb, priv->cfg.if_agc_polarity << 6, 0x40 },
{ 0x000a5, 0x00, 0x01 },
{ 0x00082, 0x20, 0x60 },

View file

@ -47,6 +47,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
{ 0x02083, 0x0a, 0xff },
{ 0x020cb, priv->cfg.if_agc_polarity << 6, 0x40 },
{ 0x02070, priv->cfg.ts_mode, 0xff },
{ 0x02071, !priv->cfg.ts_clock_inv << 6, 0x40 },
{ 0x020b5, priv->cfg.spec_inv << 4, 0x10 },
{ 0x02567, 0x07, 0x0f },
{ 0x02569, 0x03, 0x03 },

View file

@ -2557,10 +2557,19 @@ static int dib0090_set_params(struct dvb_frontend *fe)
do {
ret = dib0090_tune(fe);
if (ret != FE_CALLBACK_TIME_NEVER)
msleep(ret / 10);
else
if (ret == FE_CALLBACK_TIME_NEVER)
break;
/*
* Despite dib0090_tune returns time at a 0.1 ms range,
* the actual sleep time depends on CONFIG_HZ. The worse case
* is when CONFIG_HZ=100. In such case, the minimum granularity
* is 10ms. On some real field tests, the tuner sometimes don't
* lock when this timer is lower than 10ms. So, enforce a 10ms
* granularity and use usleep_range() instead of msleep().
*/
ret = 10 * (ret + 99)/100;
usleep_range(ret * 1000, (ret + 1) * 1000);
} while (state->tune_state != CT_TUNER_STOP);
return 0;

View file

@ -1041,10 +1041,7 @@ static int dib7000m_tune(struct dvb_frontend *demod)
u16 value;
// we are already tuned - just resuming from suspend
if (ch != NULL)
dib7000m_set_channel(state, ch, 0);
else
return -EINVAL;
dib7000m_set_channel(state, ch, 0);
// restart demod
ret |= dib7000m_write_word(state, 898, 0x4000);

View file

@ -11,6 +11,7 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <asm/div64.h>
#include "dvb_math.h"
#include "dvb_frontend.h"
@ -72,6 +73,12 @@ struct dib7000p_state {
struct mutex i2c_buffer_lock;
u8 input_mode_mpeg;
/* for DVBv5 stats */
s64 old_ucb;
unsigned long per_jiffies_stats;
unsigned long ber_jiffies_stats;
unsigned long get_stats_time;
};
enum dib7000p_power_mode {
@ -401,7 +408,7 @@ static int dib7000p_sad_calib(struct dib7000p_state *state)
return 0;
}
int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
static int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
{
struct dib7000p_state *state = demod->demodulator_priv;
if (value > 4095)
@ -409,9 +416,8 @@ int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
state->wbd_ref = value;
return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
}
EXPORT_SYMBOL(dib7000p_set_wbd_ref);
int dib7000p_get_agc_values(struct dvb_frontend *fe,
static int dib7000p_get_agc_values(struct dvb_frontend *fe,
u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
{
struct dib7000p_state *state = fe->demodulator_priv;
@ -427,14 +433,12 @@ int dib7000p_get_agc_values(struct dvb_frontend *fe,
return 0;
}
EXPORT_SYMBOL(dib7000p_get_agc_values);
int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
static int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
{
struct dib7000p_state *state = fe->demodulator_priv;
return dib7000p_write_word(state, 108, v);
}
EXPORT_SYMBOL(dib7000p_set_agc1_min);
static void dib7000p_reset_pll(struct dib7000p_state *state)
{
@ -478,7 +482,7 @@ static u32 dib7000p_get_internal_freq(struct dib7000p_state *state)
return internal;
}
int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
static int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 reg_1857, reg_1856 = dib7000p_read_word(state, 1856);
@ -513,7 +517,6 @@ int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config
}
return -EIO;
}
EXPORT_SYMBOL(dib7000p_update_pll);
static int dib7000p_reset_gpio(struct dib7000p_state *st)
{
@ -546,12 +549,11 @@ static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
return 0;
}
int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
static int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
{
struct dib7000p_state *state = demod->demodulator_priv;
return dib7000p_cfg_gpio(state, num, dir, val);
}
EXPORT_SYMBOL(dib7000p_set_gpio);
static u16 dib7000p_defaults[] = {
// auto search configuration
@ -636,6 +638,8 @@ static u16 dib7000p_defaults[] = {
0,
};
static void dib7000p_reset_stats(struct dvb_frontend *fe);
static int dib7000p_demod_reset(struct dib7000p_state *state)
{
dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
@ -934,7 +938,7 @@ static void dib7000p_update_timf(struct dib7000p_state *state)
}
u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
static u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
{
struct dib7000p_state *state = fe->demodulator_priv;
switch (op) {
@ -950,7 +954,6 @@ u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
dib7000p_set_bandwidth(state, state->current_bandwidth);
return state->timf;
}
EXPORT_SYMBOL(dib7000p_ctrl_timf);
static void dib7000p_set_channel(struct dib7000p_state *state,
struct dtv_frontend_properties *ch, u8 seq)
@ -1360,6 +1363,9 @@ static int dib7000p_tune(struct dvb_frontend *demod)
dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
dib7000p_reset_stats(demod);
return 0;
}
@ -1552,6 +1558,8 @@ static int dib7000p_set_frontend(struct dvb_frontend *fe)
return ret;
}
static int dib7000p_get_stats(struct dvb_frontend *fe, fe_status_t stat);
static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
{
struct dib7000p_state *state = fe->demodulator_priv;
@ -1570,6 +1578,8 @@ static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
if ((lock & 0x0038) == 0x38)
*stat |= FE_HAS_LOCK;
dib7000p_get_stats(fe, *stat);
return 0;
}
@ -1595,7 +1605,7 @@ static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 * strength
return 0;
}
static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr)
static u32 dib7000p_get_snr(struct dvb_frontend *fe)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 val;
@ -1625,10 +1635,351 @@ static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr)
else
result -= intlog10(2) * 10 * noise_exp - 100;
return result;
}
static int dib7000p_read_snr(struct dvb_frontend *fe, u16 *snr)
{
u32 result;
result = dib7000p_get_snr(fe);
*snr = result / ((1 << 24) / 10);
return 0;
}
static void dib7000p_reset_stats(struct dvb_frontend *demod)
{
struct dib7000p_state *state = demod->demodulator_priv;
struct dtv_frontend_properties *c = &demod->dtv_property_cache;
u32 ucb;
memset(&c->strength, 0, sizeof(c->strength));
memset(&c->cnr, 0, sizeof(c->cnr));
memset(&c->post_bit_error, 0, sizeof(c->post_bit_error));
memset(&c->post_bit_count, 0, sizeof(c->post_bit_count));
memset(&c->block_error, 0, sizeof(c->block_error));
c->strength.len = 1;
c->cnr.len = 1;
c->block_error.len = 1;
c->block_count.len = 1;
c->post_bit_error.len = 1;
c->post_bit_count.len = 1;
c->strength.stat[0].scale = FE_SCALE_DECIBEL;
c->strength.stat[0].uvalue = 0;
c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
dib7000p_read_unc_blocks(demod, &ucb);
state->old_ucb = ucb;
state->ber_jiffies_stats = 0;
state->per_jiffies_stats = 0;
}
struct linear_segments {
unsigned x;
signed y;
};
/*
* Table to estimate signal strength in dBm.
* This table should be empirically determinated by measuring the signal
* strength generated by a RF generator directly connected into
* a device.
* This table was determinated by measuring the signal strength generated
* by a DTA-2111 RF generator directly connected into a dib7000p device
* (a Hauppauge Nova-TD stick), using a good quality 3 meters length
* RC6 cable and good RC6 connectors, connected directly to antenna 1.
* As the minimum output power of DTA-2111 is -31dBm, a 16 dBm attenuator
* were used, for the lower power values.
* The real value can actually be on other devices, or even at the
* second antena input, depending on several factors, like if LNA
* is enabled or not, if diversity is enabled, type of connectors, etc.
* Yet, it is better to use this measure in dB than a random non-linear
* percentage value, especially for antenna adjustments.
* On my tests, the precision of the measure using this table is about
* 0.5 dB, with sounds reasonable enough to adjust antennas.
*/
#define DB_OFFSET 131000
static struct linear_segments strength_to_db_table[] = {
{ 63630, DB_OFFSET - 20500},
{ 62273, DB_OFFSET - 21000},
{ 60162, DB_OFFSET - 22000},
{ 58730, DB_OFFSET - 23000},
{ 58294, DB_OFFSET - 24000},
{ 57778, DB_OFFSET - 25000},
{ 57320, DB_OFFSET - 26000},
{ 56779, DB_OFFSET - 27000},
{ 56293, DB_OFFSET - 28000},
{ 55724, DB_OFFSET - 29000},
{ 55145, DB_OFFSET - 30000},
{ 54680, DB_OFFSET - 31000},
{ 54293, DB_OFFSET - 32000},
{ 53813, DB_OFFSET - 33000},
{ 53427, DB_OFFSET - 34000},
{ 52981, DB_OFFSET - 35000},
{ 52636, DB_OFFSET - 36000},
{ 52014, DB_OFFSET - 37000},
{ 51674, DB_OFFSET - 38000},
{ 50692, DB_OFFSET - 39000},
{ 49824, DB_OFFSET - 40000},
{ 49052, DB_OFFSET - 41000},
{ 48436, DB_OFFSET - 42000},
{ 47836, DB_OFFSET - 43000},
{ 47368, DB_OFFSET - 44000},
{ 46468, DB_OFFSET - 45000},
{ 45597, DB_OFFSET - 46000},
{ 44586, DB_OFFSET - 47000},
{ 43667, DB_OFFSET - 48000},
{ 42673, DB_OFFSET - 49000},
{ 41816, DB_OFFSET - 50000},
{ 40876, DB_OFFSET - 51000},
{ 0, 0},
};
static u32 interpolate_value(u32 value, struct linear_segments *segments,
unsigned len)
{
u64 tmp64;
u32 dx;
s32 dy;
int i, ret;
if (value >= segments[0].x)
return segments[0].y;
if (value < segments[len-1].x)
return segments[len-1].y;
for (i = 1; i < len - 1; i++) {
/* If value is identical, no need to interpolate */
if (value == segments[i].x)
return segments[i].y;
if (value > segments[i].x)
break;
}
/* Linear interpolation between the two (x,y) points */
dy = segments[i - 1].y - segments[i].y;
dx = segments[i - 1].x - segments[i].x;
tmp64 = value - segments[i].x;
tmp64 *= dy;
do_div(tmp64, dx);
ret = segments[i].y + tmp64;
return ret;
}
/* FIXME: may require changes - this one was borrowed from dib8000 */
static u32 dib7000p_get_time_us(struct dvb_frontend *demod, int layer)
{
struct dtv_frontend_properties *c = &demod->dtv_property_cache;
u64 time_us, tmp64;
u32 tmp, denom;
int guard, rate_num, rate_denum = 1, bits_per_symbol;
int interleaving = 0, fft_div;
switch (c->guard_interval) {
case GUARD_INTERVAL_1_4:
guard = 4;
break;
case GUARD_INTERVAL_1_8:
guard = 8;
break;
case GUARD_INTERVAL_1_16:
guard = 16;
break;
default:
case GUARD_INTERVAL_1_32:
guard = 32;
break;
}
switch (c->transmission_mode) {
case TRANSMISSION_MODE_2K:
fft_div = 4;
break;
case TRANSMISSION_MODE_4K:
fft_div = 2;
break;
default:
case TRANSMISSION_MODE_8K:
fft_div = 1;
break;
}
switch (c->modulation) {
case DQPSK:
case QPSK:
bits_per_symbol = 2;
break;
case QAM_16:
bits_per_symbol = 4;
break;
default:
case QAM_64:
bits_per_symbol = 6;
break;
}
switch ((c->hierarchy == 0 || 1 == 1) ? c->code_rate_HP : c->code_rate_LP) {
case FEC_1_2:
rate_num = 1;
rate_denum = 2;
break;
case FEC_2_3:
rate_num = 2;
rate_denum = 3;
break;
case FEC_3_4:
rate_num = 3;
rate_denum = 4;
break;
case FEC_5_6:
rate_num = 5;
rate_denum = 6;
break;
default:
case FEC_7_8:
rate_num = 7;
rate_denum = 8;
break;
}
interleaving = interleaving;
denom = bits_per_symbol * rate_num * fft_div * 384;
/* If calculus gets wrong, wait for 1s for the next stats */
if (!denom)
return 0;
/* Estimate the period for the total bit rate */
time_us = rate_denum * (1008 * 1562500L);
tmp64 = time_us;
do_div(tmp64, guard);
time_us = time_us + tmp64;
time_us += denom / 2;
do_div(time_us, denom);
tmp = 1008 * 96 * interleaving;
time_us += tmp + tmp / guard;
return time_us;
}
static int dib7000p_get_stats(struct dvb_frontend *demod, fe_status_t stat)
{
struct dib7000p_state *state = demod->demodulator_priv;
struct dtv_frontend_properties *c = &demod->dtv_property_cache;
int i;
int show_per_stats = 0;
u32 time_us = 0, val, snr;
u64 blocks, ucb;
s32 db;
u16 strength;
/* Get Signal strength */
dib7000p_read_signal_strength(demod, &strength);
val = strength;
db = interpolate_value(val,
strength_to_db_table,
ARRAY_SIZE(strength_to_db_table)) - DB_OFFSET;
c->strength.stat[0].svalue = db;
/* UCB/BER/CNR measures require lock */
if (!(stat & FE_HAS_LOCK)) {
c->cnr.len = 1;
c->block_count.len = 1;
c->block_error.len = 1;
c->post_bit_error.len = 1;
c->post_bit_count.len = 1;
c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
return 0;
}
/* Check if time for stats was elapsed */
if (time_after(jiffies, state->per_jiffies_stats)) {
state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000);
/* Get SNR */
snr = dib7000p_get_snr(demod);
if (snr)
snr = (1000L * snr) >> 24;
else
snr = 0;
c->cnr.stat[0].svalue = snr;
c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
/* Get UCB measures */
dib7000p_read_unc_blocks(demod, &val);
ucb = val - state->old_ucb;
if (val < state->old_ucb)
ucb += 0x100000000LL;
c->block_error.stat[0].scale = FE_SCALE_COUNTER;
c->block_error.stat[0].uvalue = ucb;
/* Estimate the number of packets based on bitrate */
if (!time_us)
time_us = dib7000p_get_time_us(demod, -1);
if (time_us) {
blocks = 1250000ULL * 1000000ULL;
do_div(blocks, time_us * 8 * 204);
c->block_count.stat[0].scale = FE_SCALE_COUNTER;
c->block_count.stat[0].uvalue += blocks;
}
show_per_stats = 1;
}
/* Get post-BER measures */
if (time_after(jiffies, state->ber_jiffies_stats)) {
time_us = dib7000p_get_time_us(demod, -1);
state->ber_jiffies_stats = jiffies + msecs_to_jiffies((time_us + 500) / 1000);
dprintk("Next all layers stats available in %u us.", time_us);
dib7000p_read_ber(demod, &val);
c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
c->post_bit_error.stat[0].uvalue += val;
c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
c->post_bit_count.stat[0].uvalue += 100000000;
}
/* Get PER measures */
if (show_per_stats) {
dib7000p_read_unc_blocks(demod, &val);
c->block_error.stat[0].scale = FE_SCALE_COUNTER;
c->block_error.stat[0].uvalue += val;
time_us = dib7000p_get_time_us(demod, i);
if (time_us) {
blocks = 1250000ULL * 1000000ULL;
do_div(blocks, time_us * 8 * 204);
c->block_count.stat[0].scale = FE_SCALE_COUNTER;
c->block_count.stat[0].uvalue += blocks;
}
}
return 0;
}
static int dib7000p_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
{
tune->min_delay_ms = 1000;
@ -1643,7 +1994,7 @@ static void dib7000p_release(struct dvb_frontend *demod)
kfree(st);
}
int dib7000pc_detection(struct i2c_adapter *i2c_adap)
static int dib7000pc_detection(struct i2c_adapter *i2c_adap)
{
u8 *tx, *rx;
struct i2c_msg msg[2] = {
@ -1688,16 +2039,14 @@ rx_memory_error:
kfree(tx);
return ret;
}
EXPORT_SYMBOL(dib7000pc_detection);
struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
static struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
{
struct dib7000p_state *st = demod->demodulator_priv;
return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
}
EXPORT_SYMBOL(dib7000p_get_i2c_master);
int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
static int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 val = dib7000p_read_word(state, 235) & 0xffef;
@ -1705,17 +2054,15 @@ int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
dprintk("PID filter enabled %d", onoff);
return dib7000p_write_word(state, 235, val);
}
EXPORT_SYMBOL(dib7000p_pid_filter_ctrl);
int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
static int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
{
struct dib7000p_state *state = fe->demodulator_priv;
dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
}
EXPORT_SYMBOL(dib7000p_pid_filter);
int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
static int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
{
struct dib7000p_state *dpst;
int k = 0;
@ -1774,7 +2121,6 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau
kfree(dpst);
return 0;
}
EXPORT_SYMBOL(dib7000p_i2c_enumeration);
static const s32 lut_1000ln_mant[] = {
6908, 6956, 7003, 7047, 7090, 7131, 7170, 7208, 7244, 7279, 7313, 7346, 7377, 7408, 7438, 7467, 7495, 7523, 7549, 7575, 7600
@ -2032,12 +2378,11 @@ static struct i2c_algorithm dib7090_tuner_xfer_algo = {
.functionality = dib7000p_i2c_func,
};
struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
static struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
{
struct dib7000p_state *st = fe->demodulator_priv;
return &st->dib7090_tuner_adap;
}
EXPORT_SYMBOL(dib7090_get_i2c_tuner);
static int dib7090_host_bus_drive(struct dib7000p_state *state, u8 drive)
{
@ -2329,7 +2674,7 @@ static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode)
return ret;
}
int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
static int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 en_cur_state;
@ -2352,15 +2697,13 @@ int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
return 0;
}
EXPORT_SYMBOL(dib7090_tuner_sleep);
int dib7090_get_adc_power(struct dvb_frontend *fe)
static int dib7090_get_adc_power(struct dvb_frontend *fe)
{
return dib7000p_get_adc_power(fe);
}
EXPORT_SYMBOL(dib7090_get_adc_power);
int dib7090_slave_reset(struct dvb_frontend *fe)
static int dib7090_slave_reset(struct dvb_frontend *fe)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 reg;
@ -2371,10 +2714,9 @@ int dib7090_slave_reset(struct dvb_frontend *fe)
dib7000p_write_word(state, 1032, 0xffff);
return 0;
}
EXPORT_SYMBOL(dib7090_slave_reset);
static struct dvb_frontend_ops dib7000p_ops;
struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
static struct dvb_frontend *dib7000p_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
{
struct dvb_frontend *demod;
struct dib7000p_state *st;
@ -2423,6 +2765,8 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
dib7000p_demod_reset(st);
dib7000p_reset_stats(demod);
if (st->version == SOC7090) {
dib7090_set_output_mode(demod, st->cfg.output_mode);
dib7090_set_diversity_in(demod, 0);
@ -2434,6 +2778,31 @@ error:
kfree(st);
return NULL;
}
void *dib7000p_attach(struct dib7000p_ops *ops)
{
if (!ops)
return NULL;
ops->slave_reset = dib7090_slave_reset;
ops->get_adc_power = dib7090_get_adc_power;
ops->dib7000pc_detection = dib7000pc_detection;
ops->get_i2c_tuner = dib7090_get_i2c_tuner;
ops->tuner_sleep = dib7090_tuner_sleep;
ops->init = dib7000p_init;
ops->set_agc1_min = dib7000p_set_agc1_min;
ops->set_gpio = dib7000p_set_gpio;
ops->i2c_enumeration = dib7000p_i2c_enumeration;
ops->pid_filter = dib7000p_pid_filter;
ops->pid_filter_ctrl = dib7000p_pid_filter_ctrl;
ops->get_i2c_master = dib7000p_get_i2c_master;
ops->update_pll = dib7000p_update_pll;
ops->ctrl_timf = dib7000p_ctrl_timf;
ops->get_agc_values = dib7000p_get_agc_values;
ops->set_wbd_ref = dib7000p_set_wbd_ref;
return ops;
}
EXPORT_SYMBOL(dib7000p_attach);
static struct dvb_frontend_ops dib7000p_ops = {

View file

@ -46,121 +46,34 @@ struct dib7000p_config {
#define DEFAULT_DIB7000P_I2C_ADDRESS 18
#if IS_ENABLED(CONFIG_DVB_DIB7000P)
extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
extern int dib7000p_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
extern int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
extern int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
extern u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf);
extern int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff);
extern int dib7090_get_adc_power(struct dvb_frontend *fe);
extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe);
extern int dib7090_slave_reset(struct dvb_frontend *fe);
extern int dib7000p_get_agc_values(struct dvb_frontend *fe,
struct dib7000p_ops {
int (*set_wbd_ref)(struct dvb_frontend *demod, u16 value);
int (*get_agc_values)(struct dvb_frontend *fe,
u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd);
extern int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v);
int (*set_agc1_min)(struct dvb_frontend *fe, u16 v);
int (*update_pll)(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
int (*set_gpio)(struct dvb_frontend *demod, u8 num, u8 dir, u8 val);
u32 (*ctrl_timf)(struct dvb_frontend *fe, u8 op, u32 timf);
int (*dib7000pc_detection)(struct i2c_adapter *i2c_adap);
struct i2c_adapter *(*get_i2c_master)(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating);
int (*pid_filter_ctrl)(struct dvb_frontend *fe, u8 onoff);
int (*pid_filter)(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff);
int (*i2c_enumeration)(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
struct i2c_adapter *(*get_i2c_tuner)(struct dvb_frontend *fe);
int (*tuner_sleep)(struct dvb_frontend *fe, int onoff);
int (*get_adc_power)(struct dvb_frontend *fe);
int (*slave_reset)(struct dvb_frontend *fe);
struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
};
#if IS_ENABLED(CONFIG_DVB_DIB7000P)
void *dib7000p_attach(struct dib7000p_ops *ops);
#else
static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
static inline void *dib7000p_attach(struct dib7000p_ops *ops)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface i, int x)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000pc_detection(struct i2c_adapter *i2c_adap)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, uint8_t onoff)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return 0;
}
static inline int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7090_get_adc_power(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline int dib7090_slave_reset(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000p_get_agc_values(struct dvb_frontend *fe,
u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -39,134 +39,34 @@ struct dib8000_config {
#define DEFAULT_DIB8000_I2C_ADDRESS 18
#if IS_ENABLED(CONFIG_DVB_DIB8000)
extern struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
extern struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
extern int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
u8 default_addr, u8 first_addr, u8 is_dib8096p);
extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value);
extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff);
extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
extern int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe);
extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe);
extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode);
extern struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe);
extern int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff);
extern int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ);
extern u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
uint8_t op, uint32_t timf);
extern int dib8000_update_pll(struct dvb_frontend *fe,
struct dib8000_ops {
int (*set_wbd_ref)(struct dvb_frontend *fe, u16 value);
int (*update_pll)(struct dvb_frontend *fe,
struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio);
extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe);
extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index);
int (*set_gpio)(struct dvb_frontend *fe, u8 num, u8 dir, u8 val);
void (*pwm_agc_reset)(struct dvb_frontend *fe);
struct i2c_adapter *(*get_i2c_tuner)(struct dvb_frontend *fe);
int (*tuner_sleep)(struct dvb_frontend *fe, int onoff);
s32 (*get_adc_power)(struct dvb_frontend *fe, u8 mode);
int (*get_dc_power)(struct dvb_frontend *fe, u8 IQ);
u32 (*ctrl_timf)(struct dvb_frontend *fe, uint8_t op, uint32_t timf);
enum frontend_tune_state (*get_tune_state)(struct dvb_frontend *fe);
int (*set_tune_state)(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
int (*set_slave_frontend)(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
int (*remove_slave_frontend)(struct dvb_frontend *fe);
struct dvb_frontend *(*get_slave_frontend)(struct dvb_frontend *fe, int slave_index);
int (*i2c_enumeration)(struct i2c_adapter *host, int no_of_demods,
u8 default_addr, u8 first_addr, u8 is_dib8096p);
struct i2c_adapter *(*get_i2c_master)(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating);
int (*pid_filter_ctrl)(struct dvb_frontend *fe, u8 onoff);
int (*pid_filter)(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff);
struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
};
#if IS_ENABLED(CONFIG_DVB_DIB8000)
void *dib8000_attach(struct dib8000_ops *ops);
#else
static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface i, int x)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline int dib8000_i2c_enumeration(struct i2c_adapter *host,
int no_of_demods, u8 default_addr, u8 first_addr,
u8 is_dib8096p)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return CT_SHUTDOWN;
}
static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
}
static inline struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return 0;
}
static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return 0;
}
static inline int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return 0;
}
static inline u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
uint8_t op, uint32_t timf)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return 0;
}
static inline int dib8000_update_pll(struct dvb_frontend *fe,
struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
static inline int dib8000_attach(struct dib8000_ops *ops)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;

View file

@ -1040,13 +1040,18 @@ static int dib9000_risc_apb_access_write(struct dib9000_state *state, u32 addres
if (address >= 1024 || !state->platform.risc.fw_is_running)
return -EINVAL;
if (len > 18)
return -EINVAL;
/* dprintk( "APB access thru wr fw %d %x", address, attribute); */
mb[0] = (unsigned short)address;
for (i = 0; i < len && i < 20; i += 2)
mb[1 + (i / 2)] = (b[i] << 8 | b[i + 1]);
mb[0] = (u16)address;
for (i = 0; i + 1 < len; i += 2)
mb[1 + i / 2] = b[i] << 8 | b[i + 1];
if (len & 1)
mb[1 + len / 2] = b[len - 1] << 8;
dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_W, mb, 1 + len / 2, attribute);
dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_W, mb, (3 + len) / 2, attribute);
return dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute) == 1 ? 0 : -EINVAL;
}

View file

@ -2159,7 +2159,7 @@ int drxj_dap_atomic_read_write_block(struct i2c_device_addr *dev_addr,
return 0;
rw_error:
return -EIO;
return rc;
}
@ -2252,7 +2252,7 @@ static int hi_cfg_command(const struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -2363,7 +2363,7 @@ hi_command(struct i2c_device_addr *dev_addr, const struct drxj_hi_cmd *cmd, u16
/* if ( powerdown_cmd == true ) */
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -2434,7 +2434,7 @@ static int init_hi(const struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -2650,7 +2650,7 @@ static int get_device_capabilities(struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -3338,7 +3338,7 @@ ctrl_set_cfg_mpeg_output(struct drx_demod_instance *demod, struct drx_cfg_mpeg_o
return 0;
rw_error:
return -EIO;
return rc;
}
/*----------------------------------------------------------------------------*/
@ -3421,7 +3421,7 @@ static int set_mpegtei_handling(struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/*----------------------------------------------------------------------------*/
@ -3464,7 +3464,7 @@ static int bit_reverse_mpeg_output(struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/*----------------------------------------------------------------------------*/
@ -3508,7 +3508,7 @@ static int set_mpeg_start_width(struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/*----------------------------------------------------------------------------*/
@ -3652,7 +3652,7 @@ static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -3854,7 +3854,7 @@ ctrl_uio_write(struct drx_demod_instance *demod, struct drxuio_data *uio_data)
return 0;
rw_error:
return -EIO;
return rc;
}
/*---------------------------------------------------------------------------*/
@ -3969,7 +3969,7 @@ static int smart_ant_init(struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
static int scu_command(struct i2c_device_addr *dev_addr, struct drxjscu_cmd *cmd)
@ -4109,7 +4109,7 @@ static int scu_command(struct i2c_device_addr *dev_addr, struct drxjscu_cmd *cmd
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -4178,7 +4178,7 @@ int drxj_dap_scu_atomic_read_write_block(struct i2c_device_addr *dev_addr, u32 a
return 0;
rw_error:
return -EIO;
return rc;
}
@ -4290,7 +4290,7 @@ static int adc_sync_measurement(struct drx_demod_instance *demod, u16 *count)
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -4349,7 +4349,7 @@ static int adc_synchronization(struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -4734,7 +4734,7 @@ static int init_agc(struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -4831,7 +4831,7 @@ set_frequency(struct drx_demod_instance *demod,
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -4879,7 +4879,7 @@ static int get_acc_pkt_err(struct drx_demod_instance *demod, u16 *packet_err)
return 0;
rw_error:
return -EIO;
return rc;
}
#endif
@ -5097,7 +5097,7 @@ set_agc_rf(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings,
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -5326,7 +5326,7 @@ set_agc_if(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings,
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -5362,7 +5362,7 @@ static int set_iqm_af(struct drx_demod_instance *demod, bool active)
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -5470,7 +5470,7 @@ static int power_down_vsb(struct drx_demod_instance *demod, bool primary)
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -5686,7 +5686,7 @@ static int set_vsb_leak_n_gain(struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -6192,7 +6192,7 @@ static int set_vsb(struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -6231,7 +6231,7 @@ static int get_vsb_post_rs_pck_err(struct i2c_device_addr *dev_addr,
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -6276,7 +6276,7 @@ static int get_vs_bpost_viterbi_ber(struct i2c_device_addr *dev_addr,
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -6321,7 +6321,7 @@ static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer)
return 0;
rw_error:
return -EIO;
return rc;
}
@ -6434,7 +6434,7 @@ static int power_down_qam(struct drx_demod_instance *demod, bool primary)
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -6646,7 +6646,7 @@ set_qam_measurement(struct drx_demod_instance *demod,
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -6881,7 +6881,7 @@ static int set_qam16(struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -7116,7 +7116,7 @@ static int set_qam32(struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -7351,7 +7351,7 @@ static int set_qam64(struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -7586,7 +7586,7 @@ static int set_qam128(struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -7821,7 +7821,7 @@ static int set_qam256(struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -8650,7 +8650,7 @@ set_qam(struct drx_demod_instance *demod,
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -8831,7 +8831,7 @@ static int qam_flip_spec(struct drx_demod_instance *demod, struct drx_channel *c
return 0;
rw_error:
return -EIO;
return rc;
}
@ -8984,7 +8984,7 @@ qam64auto(struct drx_demod_instance *demod,
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -9068,7 +9068,7 @@ qam256auto(struct drx_demod_instance *demod,
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -9273,7 +9273,7 @@ rw_error:
/* restore starting value */
if (auto_flag)
channel->constellation = DRX_CONSTELLATION_AUTO;
return -EIO;
return rc;
}
/*============================================================================*/
@ -9344,7 +9344,7 @@ get_qamrs_err_count(struct i2c_device_addr *dev_addr,
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -9425,8 +9425,8 @@ static int get_sig_strength(struct drx_demod_instance *demod, u16 *sig_strength)
*sig_strength = 0;
return 0;
rw_error:
return -EIO;
rw_error:
return rc;
}
/**
@ -9643,7 +9643,7 @@ rw_error:
p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
return -EIO;
return rc;
}
#endif /* #ifndef DRXJ_VSB_ONLY */
@ -9810,7 +9810,7 @@ power_down_atv(struct drx_demod_instance *demod, enum drx_standard standard, boo
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -9840,7 +9840,7 @@ static int power_down_aud(struct drx_demod_instance *demod)
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -9874,7 +9874,7 @@ static int set_orx_nsu_aox(struct drx_demod_instance *demod, bool active)
return 0;
rw_error:
return -EIO;
return rc;
}
/**
@ -10398,7 +10398,7 @@ static int ctrl_set_oob(struct drx_demod_instance *demod, struct drxoob *oob_par
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -10638,7 +10638,7 @@ ctrl_set_channel(struct drx_demod_instance *demod, struct drx_channel *channel)
return 0;
rw_error:
return -EIO;
return rc;
}
/*=============================================================================
@ -10756,7 +10756,7 @@ ctrl_sig_quality(struct drx_demod_instance *demod,
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -10844,7 +10844,7 @@ ctrl_lock_status(struct drx_demod_instance *demod, enum drx_lock_status *lock_st
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -10941,7 +10941,7 @@ ctrl_set_standard(struct drx_demod_instance *demod, enum drx_standard *standard)
rw_error:
/* Don't know what the standard is now ... try again */
ext_attr->standard = DRX_STANDARD_UNKNOWN;
return -EIO;
return rc;
}
/*============================================================================*/
@ -11222,7 +11222,7 @@ ctrl_set_cfg_pre_saw(struct drx_demod_instance *demod, struct drxj_cfg_pre_saw *
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -11303,7 +11303,7 @@ ctrl_set_cfg_afe_gain(struct drx_demod_instance *demod, struct drxj_cfg_afe_gain
return 0;
rw_error:
return -EIO;
return rc;
}
/*============================================================================*/
@ -11315,6 +11315,7 @@ rw_error:
static int drx_ctrl_u_code(struct drx_demod_instance *demod,
struct drxu_code_info *mc_info,
enum drxu_code_action action);
static int drxj_set_lna_state(struct drx_demod_instance *demod, bool state);
/**
* \fn drxj_open()
@ -11527,10 +11528,11 @@ static int drxj_open(struct drx_demod_instance *demod)
ext_attr->aud_data = drxj_default_aud_data_g;
demod->my_common_attr->is_opened = true;
drxj_set_lna_state(demod, false);
return 0;
rw_error:
common_attr->is_opened = false;
return -EIO;
return rc;
}
/*============================================================================*/
@ -11578,7 +11580,7 @@ static int drxj_close(struct drx_demod_instance *demod)
rw_error:
DRX_ATTR_ISOPENED(demod) = false;
return -EIO;
return rc;
}
/*
@ -11890,6 +11892,33 @@ release:
return rc;
}
/* caller is expeced to check if lna is supported before enabling */
static int drxj_set_lna_state(struct drx_demod_instance *demod, bool state)
{
struct drxuio_cfg uio_cfg;
struct drxuio_data uio_data;
int result;
uio_cfg.uio = DRX_UIO1;
uio_cfg.mode = DRX_UIO_MODE_READWRITE;
/* Configure user-I/O #3: enable read/write */
result = ctrl_set_uio_cfg(demod, &uio_cfg);
if (result) {
pr_err("Failed to setup LNA GPIO!\n");
return result;
}
uio_data.uio = DRX_UIO1;
uio_data.value = state;
result = ctrl_uio_write(demod, &uio_data);
if (result != 0) {
pr_err("Failed to %sable LNA!\n",
state ? "en" : "dis");
return result;
}
return 0;
}
/*
* The Linux DVB Driver for Micronas DRX39xx family (drx3933j)
*
@ -12040,7 +12069,6 @@ static int drx39xxj_set_frontend(struct dvb_frontend *fe)
enum drx_standard standard = DRX_STANDARD_8VSB;
struct drx_channel channel;
int result;
struct drxuio_data uio_data;
static const struct drx_channel def_channel = {
/* frequency */ 0,
/* bandwidth */ DRX_BANDWIDTH_6MHZ,
@ -12125,13 +12153,7 @@ static int drx39xxj_set_frontend(struct dvb_frontend *fe)
return -EINVAL;
}
/* Just for giggles, let's shut off the LNA again.... */
uio_data.uio = DRX_UIO1;
uio_data.value = false;
result = ctrl_uio_write(demod, &uio_data);
if (result != 0) {
pr_err("Failed to disable LNA!\n");
return 0;
}
drxj_set_lna_state(demod, false);
/* After set_frontend, except for strength, stats aren't available */
p->strength.stat[0].scale = FE_SCALE_RELATIVE;
@ -12180,21 +12202,28 @@ static int drx39xxj_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
static int drx39xxj_init(struct dvb_frontend *fe)
{
/* Bring the demod out of sleep */
drx39xxj_set_powerstate(fe, 1);
struct drx39xxj_state *state = fe->demodulator_priv;
struct drx_demod_instance *demod = state->demod;
int rc = 0;
return 0;
if (fe->exit == DVB_FE_DEVICE_RESUME) {
/* so drxj_open() does what it needs to do */
demod->my_common_attr->is_opened = false;
rc = drxj_open(demod);
if (rc != 0)
pr_err("drx39xxj_init(): DRX open failed rc=%d!\n", rc);
} else
drx39xxj_set_powerstate(fe, 1);
return rc;
}
static int drx39xxj_set_lna(struct dvb_frontend *fe)
{
int result;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct drx39xxj_state *state = fe->demodulator_priv;
struct drx_demod_instance *demod = state->demod;
struct drxj_data *ext_attr = demod->my_ext_attr;
struct drxuio_cfg uio_cfg;
struct drxuio_data uio_data;
if (c->lna) {
if (!ext_attr->has_lna) {
@ -12204,26 +12233,7 @@ static int drx39xxj_set_lna(struct dvb_frontend *fe)
}
}
/* Turn off the LNA */
uio_cfg.uio = DRX_UIO1;
uio_cfg.mode = DRX_UIO_MODE_READWRITE;
/* Configure user-I/O #3: enable read/write */
result = ctrl_set_uio_cfg(demod, &uio_cfg);
if (result) {
pr_err("Failed to setup LNA GPIO!\n");
return result;
}
uio_data.uio = DRX_UIO1;
uio_data.value = c->lna;
result = ctrl_uio_write(demod, &uio_data);
if (result != 0) {
pr_err("Failed to %sable LNA!\n",
c->lna ? "en" : "dis");
return result;
}
return 0;
return drxj_set_lna_state(demod, c->lna);
}
static int drx39xxj_get_tune_settings(struct dvb_frontend *fe,
@ -12238,7 +12248,9 @@ static void drx39xxj_release(struct dvb_frontend *fe)
struct drx39xxj_state *state = fe->demodulator_priv;
struct drx_demod_instance *demod = state->demod;
drxj_close(demod);
/* if device is removed don't access it */
if (fe->exit != DVB_FE_DEVICE_REMOVED)
drxj_close(demod);
kfree(demod->my_ext_attr);
kfree(demod->my_common_attr);
@ -12259,8 +12271,6 @@ struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c)
struct drxj_data *demod_ext_attr = NULL;
struct drx_demod_instance *demod = NULL;
struct dtv_frontend_properties *p;
struct drxuio_cfg uio_cfg;
struct drxuio_data uio_data;
int result;
/* allocate memory for the internal state */
@ -12272,22 +12282,20 @@ struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c)
if (demod == NULL)
goto error;
demod_addr = kmalloc(sizeof(struct i2c_device_addr), GFP_KERNEL);
demod_addr = kmemdup(&drxj_default_addr_g,
sizeof(struct i2c_device_addr), GFP_KERNEL);
if (demod_addr == NULL)
goto error;
memcpy(demod_addr, &drxj_default_addr_g,
sizeof(struct i2c_device_addr));
demod_comm_attr = kmalloc(sizeof(struct drx_common_attr), GFP_KERNEL);
demod_comm_attr = kmemdup(&drxj_default_comm_attr_g,
sizeof(struct drx_common_attr), GFP_KERNEL);
if (demod_comm_attr == NULL)
goto error;
memcpy(demod_comm_attr, &drxj_default_comm_attr_g,
sizeof(struct drx_common_attr));
demod_ext_attr = kmalloc(sizeof(struct drxj_data), GFP_KERNEL);
demod_ext_attr = kmemdup(&drxj_data_g, sizeof(struct drxj_data),
GFP_KERNEL);
if (demod_ext_attr == NULL)
goto error;
memcpy(demod_ext_attr, &drxj_data_g, sizeof(struct drxj_data));
/* setup the state */
state->i2c = i2c;
@ -12313,24 +12321,6 @@ struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c)
goto error;
}
/* Turn off the LNA */
uio_cfg.uio = DRX_UIO1;
uio_cfg.mode = DRX_UIO_MODE_READWRITE;
/* Configure user-I/O #3: enable read/write */
result = ctrl_set_uio_cfg(demod, &uio_cfg);
if (result) {
pr_err("Failed to setup LNA GPIO!\n");
goto error;
}
uio_data.uio = DRX_UIO1;
uio_data.value = false;
result = ctrl_uio_write(demod, &uio_data);
if (result != 0) {
pr_err("Failed to disable LNA!\n");
goto error;
}
/* create dvb_frontend */
memcpy(&state->frontend.ops, &drx39xxj_ops,
sizeof(struct dvb_frontend_ops));

View file

@ -69,5 +69,4 @@ struct dvb_frontend *drxd_attach(const struct drxd_config *config,
}
#endif
extern int drxd_config_i2c(struct dvb_frontend *, int);
#endif

View file

@ -2840,7 +2840,7 @@ static int drxd_init(struct dvb_frontend *fe)
return err;
}
int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
static int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
{
struct drxd_state *state = fe->demodulator_priv;
@ -2849,7 +2849,6 @@ int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
return DRX_ConfigureI2CBridge(state, onoff);
}
EXPORT_SYMBOL(drxd_config_i2c);
static int drxd_get_tune_settings(struct dvb_frontend *fe,
struct dvb_frontend_tune_settings *sets)

View file

@ -879,7 +879,7 @@ static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *snr)
/* SNR(X) dB = 10 * ln(X) / ln(10) dB */
tmp = DIV_ROUND_CLOSEST(tmp, 8 * M88DS3103_SNR_ITERATIONS);
if (tmp)
*snr = 100ul * intlog2(tmp) / intlog2(10);
*snr = div_u64((u64) 100 * intlog2(tmp), intlog2(10));
else
*snr = 0;
break;
@ -908,7 +908,7 @@ static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *snr)
/* SNR(X) dB = 10 * log10(X) dB */
if (signal > noise) {
tmp = signal / noise;
*snr = 100ul * intlog10(tmp) / (1 << 24);
*snr = div_u64((u64) 100 * intlog10(tmp), (1 << 24));
} else {
*snr = 0;
}
@ -926,6 +926,86 @@ err:
return ret;
}
static int m88ds3103_read_ber(struct dvb_frontend *fe, u32 *ber)
{
struct m88ds3103_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
unsigned int utmp;
u8 buf[3], u8tmp;
dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
switch (c->delivery_system) {
case SYS_DVBS:
ret = m88ds3103_wr_reg(priv, 0xf9, 0x04);
if (ret)
goto err;
ret = m88ds3103_rd_reg(priv, 0xf8, &u8tmp);
if (ret)
goto err;
if (!(u8tmp & 0x10)) {
u8tmp |= 0x10;
ret = m88ds3103_rd_regs(priv, 0xf6, buf, 2);
if (ret)
goto err;
priv->ber = (buf[1] << 8) | (buf[0] << 0);
/* restart counters */
ret = m88ds3103_wr_reg(priv, 0xf8, u8tmp);
if (ret)
goto err;
}
break;
case SYS_DVBS2:
ret = m88ds3103_rd_regs(priv, 0xd5, buf, 3);
if (ret)
goto err;
utmp = (buf[2] << 16) | (buf[1] << 8) | (buf[0] << 0);
if (utmp > 3000) {
ret = m88ds3103_rd_regs(priv, 0xf7, buf, 2);
if (ret)
goto err;
priv->ber = (buf[1] << 8) | (buf[0] << 0);
/* restart counters */
ret = m88ds3103_wr_reg(priv, 0xd1, 0x01);
if (ret)
goto err;
ret = m88ds3103_wr_reg(priv, 0xf9, 0x01);
if (ret)
goto err;
ret = m88ds3103_wr_reg(priv, 0xf9, 0x00);
if (ret)
goto err;
ret = m88ds3103_wr_reg(priv, 0xd1, 0x00);
if (ret)
goto err;
}
break;
default:
dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n",
__func__);
ret = -EINVAL;
goto err;
}
*ber = priv->ber;
return 0;
err:
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
static int m88ds3103_set_tone(struct dvb_frontend *fe,
fe_sec_tone_mode_t fe_sec_tone_mode)
@ -1284,6 +1364,7 @@ static struct dvb_frontend_ops m88ds3103_ops = {
.read_status = m88ds3103_read_status,
.read_snr = m88ds3103_read_snr,
.read_ber = m88ds3103_read_ber,
.diseqc_send_master_cmd = m88ds3103_diseqc_send_master_cmd,
.diseqc_send_burst = m88ds3103_diseqc_send_burst,

View file

@ -22,6 +22,7 @@
#include "dvb_math.h"
#include <linux/firmware.h>
#include <linux/i2c-mux.h>
#include <linux/math64.h>
#define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw"
#define M88DS3103_MCLK_KHZ 96000
@ -34,6 +35,7 @@ struct m88ds3103_priv {
struct dvb_frontend fe;
fe_delivery_system_t delivery_system;
fe_status_t fe_status;
u32 ber;
bool warm; /* FW running */
struct i2c_adapter *i2c_adapter;
};

View file

@ -459,6 +459,9 @@ static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
unsigned layer)
{
int rc;
int interleaving[] = {
0, 1, 2, 4, 8
};
static unsigned char reg[] = {
[0] = 0x88, /* Layer A */
@ -475,20 +478,7 @@ static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
if (rc < 0)
return rc;
switch ((rc >> 4) & 0x07) {
case 1:
return GUARD_INTERVAL_1_4;
case 2:
return GUARD_INTERVAL_1_8;
case 3:
return GUARD_INTERVAL_1_16;
case 4:
return GUARD_INTERVAL_1_32;
default:
case 0:
return GUARD_INTERVAL_AUTO;
}
return interleaving[(rc >> 4) & 0x07];
}
static int mb86a20s_get_segment_count(struct mb86a20s_state *state,
@ -566,7 +556,7 @@ static u32 isdbt_rate[3][5][4] = {
static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer,
u32 modulation, u32 forward_error_correction,
u32 interleaving,
u32 guard_interval,
u32 segment)
{
struct mb86a20s_state *state = fe->demodulator_priv;
@ -574,7 +564,7 @@ static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer,
int mod, fec, guard;
/*
* If modulation/fec/interleaving is not detected, the default is
* If modulation/fec/guard is not detected, the default is
* to consider the lowest bit rate, to avoid taking too long time
* to get BER.
*/
@ -612,7 +602,7 @@ static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer,
break;
}
switch (interleaving) {
switch (guard_interval) {
default:
case GUARD_INTERVAL_1_4:
guard = 0;
@ -703,7 +693,7 @@ static int mb86a20s_get_frontend(struct dvb_frontend *fe)
c->layer[layer].interleaving = rc;
mb86a20s_layer_bitrate(fe, layer, c->layer[layer].modulation,
c->layer[layer].fec,
c->layer[layer].interleaving,
c->guard_interval,
c->layer[layer].segment_count);
}
@ -721,11 +711,10 @@ static int mb86a20s_get_frontend(struct dvb_frontend *fe)
rc = mb86a20s_readreg(state, 0x07);
if (rc < 0)
return rc;
c->transmission_mode = TRANSMISSION_MODE_AUTO;
if ((rc & 0x60) == 0x20) {
switch (rc & 0x0c >> 2) {
case 0:
c->transmission_mode = TRANSMISSION_MODE_2K;
break;
/* Only modes 2 and 3 are supported */
switch ((rc >> 2) & 0x03) {
case 1:
c->transmission_mode = TRANSMISSION_MODE_4K;
break;
@ -734,7 +723,9 @@ static int mb86a20s_get_frontend(struct dvb_frontend *fe)
break;
}
}
c->guard_interval = GUARD_INTERVAL_AUTO;
if (!(rc & 0x10)) {
/* Guard interval 1/32 is not supported */
switch (rc & 0x3) {
case 0:
c->guard_interval = GUARD_INTERVAL_1_4;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,54 @@
/*
* Realtek RTL2832U SDR driver
*
* Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* GNU Radio plugin "gr-kernel" for device usage will be on:
* http://git.linuxtv.org/anttip/gr-kernel.git
*
* TODO:
* Help is very highly welcome for these + all the others you could imagine:
* - move controls to V4L2 API
* - use libv4l2 for stream format conversions
* - gr-kernel: switch to v4l2_mmap (current read eats a lot of cpu)
* - SDRSharp support
*/
#ifndef RTL2832_SDR_H
#define RTL2832_SDR_H
#include <linux/kconfig.h>
#include <media/v4l2-subdev.h>
/* for config struct */
#include "rtl2832.h"
#if IS_ENABLED(CONFIG_DVB_RTL2832_SDR)
extern struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
struct v4l2_subdev *sd);
#else
static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
struct v4l2_subdev *sd)
{
dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
#endif /* RTL2832_SDR_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,62 @@
/*
Driver for Silicon Labs SI2165 DVB-C/-T Demodulator
Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.org>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but 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.
References:
http://www.silabs.com/Support%20Documents/TechnicalDocs/Si2165-short.pdf
*/
#ifndef _DVB_SI2165_H
#define _DVB_SI2165_H
#include <linux/dvb/frontend.h>
enum {
SI2165_MODE_OFF = 0x00,
SI2165_MODE_PLL_EXT = 0x20,
SI2165_MODE_PLL_XTAL = 0x21
};
struct si2165_config {
/* i2c addr
* possible values: 0x64,0x65,0x66,0x67 */
u8 i2c_addr;
/* external clock or XTAL */
u8 chip_mode;
/* frequency of external clock or xtal in Hz
* possible values: 4000000, 16000000, 20000000, 240000000, 27000000
*/
u32 ref_freq_Hz;
/* invert the spectrum */
bool inversion;
};
#if IS_ENABLED(CONFIG_DVB_SI2165)
struct dvb_frontend *si2165_attach(
const struct si2165_config *config,
struct i2c_adapter *i2c);
#else
static inline struct dvb_frontend *si2165_attach(
const struct si2165_config *config,
struct i2c_adapter *i2c)
{
pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_SI2165 */
#endif /* _DVB_SI2165_H */

View file

@ -0,0 +1,23 @@
/*
Driver for Silicon Labs SI2165 DVB-C/-T Demodulator
Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.org>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but 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.
*/
#ifndef _DVB_SI2165_PRIV
#define _DVB_SI2165_PRIV
#define SI2165_FIRMWARE "dvb-demod-si2165.fw"
#endif /* _DVB_SI2165_PRIV */

View file

@ -95,20 +95,17 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
switch (c->delivery_system) {
case SYS_DVBT:
cmd.args[0] = 0xa0;
cmd.args[1] = 0x01;
memcpy(cmd.args, "\xa0\x01", 2);
cmd.wlen = 2;
cmd.rlen = 13;
break;
case SYS_DVBC_ANNEX_A:
cmd.args[0] = 0x90;
cmd.args[1] = 0x01;
memcpy(cmd.args, "\x90\x01", 2);
cmd.wlen = 2;
cmd.rlen = 9;
break;
case SYS_DVBT2:
cmd.args[0] = 0x50;
cmd.args[1] = 0x01;
memcpy(cmd.args, "\x50\x01", 2);
cmd.wlen = 2;
cmd.rlen = 14;
break;
@ -144,6 +141,15 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
s->fe_status = *status;
if (*status & FE_HAS_LOCK) {
c->cnr.len = 1;
c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
c->cnr.stat[0].svalue = cmd.args[3] * 1000 / 4;
} else {
c->cnr.len = 1;
c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
}
dev_dbg(&s->client->dev, "%s: status=%02x args=%*ph\n",
__func__, *status, cmd.rlen, cmd.args);
@ -243,51 +249,23 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x01\x04\x00\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x03\x10\x17\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x02\x10\x15\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x0b\x10\x88\x13", 6);
cmd.wlen = 6;
cmd.rlen = 1;
cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6);
cmd.wlen = 6;
cmd.rlen = 1;
cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
@ -295,124 +273,66 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
memcpy(cmd.args, "\x14\x00\x0a\x10\x00\x00", 6);
cmd.args[4] = delivery_system | bandwidth;
cmd.wlen = 6;
cmd.rlen = 1;
cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x04\x10\x15\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x05\x10\xa1\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
/* set DVB-C symbol rate */
if (c->delivery_system == SYS_DVBC_ANNEX_A) {
memcpy(cmd.args, "\x14\x00\x02\x11", 4);
cmd.args[4] = (c->symbol_rate / 1000) & 0xff;
cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff;
cmd.wlen = 6;
cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
}
memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x0d\x10\xd0\x02", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x01\x10\x00\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x18", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x15", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x04\x03\x00\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x03\x03\x00\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x08\x03\x00\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x07\x03\x01\x02", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x06\x03\x00\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x05\x03\x00\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x40", 6);
cmd.wlen = 6;
cmd.rlen = 1;
cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x01\x10\x16\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x18", 6);
cmd.wlen = 6;
cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x15", 6);
cmd.wlen = 6;
cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6);
cmd.wlen = 6;
cmd.rlen = 1;
cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
cmd.args[0] = 0x85;
memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x00", 6);
cmd.wlen = 6;
cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x85", 1);
cmd.wlen = 1;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
@ -432,59 +352,61 @@ static int si2168_init(struct dvb_frontend *fe)
struct si2168 *s = fe->demodulator_priv;
int ret, len, remaining;
const struct firmware *fw = NULL;
u8 *fw_file = SI2168_FIRMWARE;
u8 *fw_file;
const unsigned int i2c_wr_max = 8;
struct si2168_cmd cmd;
unsigned int chip_id;
dev_dbg(&s->client->dev, "%s:\n", __func__);
cmd.args[0] = 0x13;
cmd.wlen = 1;
cmd.rlen = 0;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
cmd.args[0] = 0xc0;
cmd.args[1] = 0x12;
cmd.args[2] = 0x00;
cmd.args[3] = 0x0c;
cmd.args[4] = 0x00;
cmd.args[5] = 0x0d;
cmd.args[6] = 0x16;
cmd.args[7] = 0x00;
cmd.args[8] = 0x00;
cmd.args[9] = 0x00;
cmd.args[10] = 0x00;
cmd.args[11] = 0x00;
cmd.args[12] = 0x00;
memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13);
cmd.wlen = 13;
cmd.rlen = 0;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
cmd.args[0] = 0xc0;
cmd.args[1] = 0x06;
cmd.args[2] = 0x01;
cmd.args[3] = 0x0f;
cmd.args[4] = 0x00;
cmd.args[5] = 0x20;
cmd.args[6] = 0x20;
cmd.args[7] = 0x01;
memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8);
cmd.wlen = 8;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
cmd.args[0] = 0x02;
/* query chip revision */
memcpy(cmd.args, "\x02", 1);
cmd.wlen = 1;
cmd.rlen = 13;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
cmd.args[4] << 0;
#define SI2168_A20 ('A' << 24 | 68 << 16 | '2' << 8 | '0' << 0)
#define SI2168_A30 ('A' << 24 | 68 << 16 | '3' << 8 | '0' << 0)
#define SI2168_B40 ('B' << 24 | 68 << 16 | '4' << 8 | '0' << 0)
switch (chip_id) {
case SI2168_A20:
fw_file = SI2168_A20_FIRMWARE;
break;
case SI2168_A30:
fw_file = SI2168_A30_FIRMWARE;
break;
case SI2168_B40:
fw_file = SI2168_B40_FIRMWARE;
break;
default:
dev_err(&s->client->dev,
"%s: unkown chip version Si21%d-%c%c%c\n",
KBUILD_MODNAME, cmd.args[2], cmd.args[1],
cmd.args[3], cmd.args[4]);
ret = -EINVAL;
goto err;
}
/* cold state - try to download firmware */
dev_info(&s->client->dev, "%s: found a '%s' in cold state\n",
KBUILD_MODNAME, si2168_ops.info.name);
@ -492,9 +414,22 @@ static int si2168_init(struct dvb_frontend *fe)
/* request the firmware, this will block and timeout */
ret = request_firmware(&fw, fw_file, &s->client->dev);
if (ret) {
dev_err(&s->client->dev, "%s: firmare file '%s' not found\n",
KBUILD_MODNAME, fw_file);
goto err;
/* fallback mechanism to handle old name for Si2168 B40 fw */
if (chip_id == SI2168_B40) {
fw_file = SI2168_B40_FIRMWARE_FALLBACK;
ret = request_firmware(&fw, fw_file, &s->client->dev);
}
if (ret == 0) {
dev_notice(&s->client->dev,
"%s: please install firmware file '%s'\n",
KBUILD_MODNAME, SI2168_B40_FIRMWARE);
} else {
dev_err(&s->client->dev,
"%s: firmware file '%s' not found\n",
KBUILD_MODNAME, fw_file);
goto err;
}
}
dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n",
@ -520,8 +455,7 @@ static int si2168_init(struct dvb_frontend *fe)
release_firmware(fw);
fw = NULL;
cmd.args[0] = 0x01;
cmd.args[1] = 0x01;
memcpy(cmd.args, "\x01\x01", 2);
cmd.wlen = 2;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
@ -545,12 +479,24 @@ err:
static int si2168_sleep(struct dvb_frontend *fe)
{
struct si2168 *s = fe->demodulator_priv;
int ret;
struct si2168_cmd cmd;
dev_dbg(&s->client->dev, "%s:\n", __func__);
s->active = false;
memcpy(cmd.args, "\x13", 1);
cmd.wlen = 1;
cmd.rlen = 0;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
return 0;
err:
dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
static int si2168_get_tune_settings(struct dvb_frontend *fe,
@ -660,7 +606,6 @@ static int si2168_probe(struct i2c_client *client,
struct si2168_config *config = client->dev.platform_data;
struct si2168 *s;
int ret;
struct si2168_cmd cmd;
dev_dbg(&client->dev, "%s:\n", __func__);
@ -674,18 +619,13 @@ static int si2168_probe(struct i2c_client *client,
s->client = client;
mutex_init(&s->i2c_mutex);
/* check if the demod is there */
cmd.wlen = 0;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
/* create mux i2c adapter for tuner */
s->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, s,
0, 0, 0, si2168_select, si2168_deselect);
if (s->adapter == NULL)
if (s->adapter == NULL) {
ret = -ENODEV;
goto err;
}
/* create dvb_frontend */
memcpy(&s->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops));
@ -743,4 +683,6 @@ module_i2c_driver(si2168_driver);
MODULE_AUTHOR("Antti Palosaari <[email protected]>");
MODULE_DESCRIPTION("Silicon Labs Si2168 DVB-T/T2/C demodulator driver");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(SI2168_FIRMWARE);
MODULE_FIRMWARE(SI2168_A20_FIRMWARE);
MODULE_FIRMWARE(SI2168_A30_FIRMWARE);
MODULE_FIRMWARE(SI2168_B40_FIRMWARE);

View file

@ -22,7 +22,10 @@
#include <linux/firmware.h>
#include <linux/i2c-mux.h>
#define SI2168_FIRMWARE "dvb-demod-si2168-02.fw"
#define SI2168_A20_FIRMWARE "dvb-demod-si2168-a20-01.fw"
#define SI2168_A30_FIRMWARE "dvb-demod-si2168-a30-01.fw"
#define SI2168_B40_FIRMWARE "dvb-demod-si2168-b40-01.fw"
#define SI2168_B40_FIRMWARE_FALLBACK "dvb-demod-si2168-02.fw"
/* state struct */
struct si2168 {
@ -36,9 +39,9 @@ struct si2168 {
};
/* firmare command struct */
#define SI2157_ARGLEN 30
#define SI2168_ARGLEN 30
struct si2168_cmd {
u8 args[SI2157_ARGLEN];
u8 args[SI2168_ARGLEN];
unsigned wlen;
unsigned rlen;
};

View file

@ -21,17 +21,14 @@
static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
struct dvb_frontend_ops *frontend_ops = NULL;
struct dvb_tuner_ops *tuner_ops = NULL;
struct dvb_frontend_ops *frontend_ops = &fe->ops;
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state t_state;
int err = 0;
if (&fe->ops)
frontend_ops = &fe->ops;
if (&frontend_ops->tuner_ops)
tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->get_state) {
if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
if (err < 0) {
printk("%s: Invalid parameter\n", __func__);
return err;
}
@ -42,18 +39,16 @@ static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
{
struct dvb_frontend_ops *frontend_ops = NULL;
struct dvb_tuner_ops *tuner_ops = NULL;
struct dvb_frontend_ops *frontend_ops = &fe->ops;
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state t_state;
int err = 0;
t_state.frequency = frequency;
if (&fe->ops)
frontend_ops = &fe->ops;
if (&frontend_ops->tuner_ops)
tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->set_state) {
if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
if (err < 0) {
printk("%s: Invalid parameter\n", __func__);
return err;
}
@ -68,12 +63,9 @@ static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
struct tuner_state t_state;
int err = 0;
if (&fe->ops)
frontend_ops = &fe->ops;
if (&frontend_ops->tuner_ops)
tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->get_state) {
if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state);
if (err < 0) {
printk("%s: Invalid parameter\n", __func__);
return err;
}
@ -84,18 +76,16 @@ static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
{
struct dvb_frontend_ops *frontend_ops = NULL;
struct dvb_tuner_ops *tuner_ops = NULL;
struct dvb_frontend_ops *frontend_ops = &fe->ops;
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state t_state;
int err = 0;
t_state.bandwidth = bandwidth;
if (&fe->ops)
frontend_ops = &fe->ops;
if (&frontend_ops->tuner_ops)
tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->set_state) {
if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state);
if (err < 0) {
printk("%s: Invalid parameter\n", __func__);
return err;
}

View file

@ -19,15 +19,11 @@
static int stb6100_get_freq(struct dvb_frontend *fe, u32 *frequency)
{
struct dvb_frontend_ops *frontend_ops = NULL;
struct dvb_tuner_ops *tuner_ops = NULL;
struct dvb_frontend_ops *frontend_ops = &fe->ops;
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state state;
int err = 0;
if (&fe->ops)
frontend_ops = &fe->ops;
if (&frontend_ops->tuner_ops)
tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->get_state) {
if (frontend_ops->i2c_gate_ctrl)
frontend_ops->i2c_gate_ctrl(fe, 1);
@ -49,16 +45,13 @@ static int stb6100_get_freq(struct dvb_frontend *fe, u32 *frequency)
static int stb6100_set_freq(struct dvb_frontend *fe, u32 frequency)
{
struct dvb_frontend_ops *frontend_ops = NULL;
struct dvb_tuner_ops *tuner_ops = NULL;
struct dvb_frontend_ops *frontend_ops = &fe->ops;
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state state;
int err = 0;
state.frequency = frequency;
if (&fe->ops)
frontend_ops = &fe->ops;
if (&frontend_ops->tuner_ops)
tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->set_state) {
if (frontend_ops->i2c_gate_ctrl)
frontend_ops->i2c_gate_ctrl(fe, 1);
@ -79,15 +72,11 @@ static int stb6100_set_freq(struct dvb_frontend *fe, u32 frequency)
static int stb6100_get_bandw(struct dvb_frontend *fe, u32 *bandwidth)
{
struct dvb_frontend_ops *frontend_ops = NULL;
struct dvb_tuner_ops *tuner_ops = NULL;
struct dvb_frontend_ops *frontend_ops = &fe->ops;
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state state;
int err = 0;
if (&fe->ops)
frontend_ops = &fe->ops;
if (&frontend_ops->tuner_ops)
tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->get_state) {
if (frontend_ops->i2c_gate_ctrl)
frontend_ops->i2c_gate_ctrl(fe, 1);
@ -109,16 +98,13 @@ static int stb6100_get_bandw(struct dvb_frontend *fe, u32 *bandwidth)
static int stb6100_set_bandw(struct dvb_frontend *fe, u32 bandwidth)
{
struct dvb_frontend_ops *frontend_ops = NULL;
struct dvb_tuner_ops *tuner_ops = NULL;
struct dvb_frontend_ops *frontend_ops = &fe->ops;
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state state;
int err = 0;
state.bandwidth = bandwidth;
if (&fe->ops)
frontend_ops = &fe->ops;
if (&frontend_ops->tuner_ops)
tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->set_state) {
if (frontend_ops->i2c_gate_ctrl)
frontend_ops->i2c_gate_ctrl(fe, 1);

View file

@ -922,18 +922,13 @@ static int stv0367ter_gate_ctrl(struct dvb_frontend *fe, int enable)
static u32 stv0367_get_tuner_freq(struct dvb_frontend *fe)
{
struct dvb_frontend_ops *frontend_ops = NULL;
struct dvb_tuner_ops *tuner_ops = NULL;
struct dvb_frontend_ops *frontend_ops = &fe->ops;
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
u32 freq = 0;
int err = 0;
dprintk("%s:\n", __func__);
if (&fe->ops)
frontend_ops = &fe->ops;
if (&frontend_ops->tuner_ops)
tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->get_frequency) {
err = tuner_ops->get_frequency(fe, &freq);
if (err < 0) {

View file

@ -1030,7 +1030,7 @@ static int ChannelConfiguration(struct tda_state *state,
state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital;
if ((Standard == HF_FM_Radio) && state->m_bFMInput)
state->m_Regs[EP4] |= 80;
state->m_Regs[EP4] |= 0x80;
state->m_Regs[MPD] &= ~0x80;
if (Standard > HF_AnalogMax)

View file

@ -5,7 +5,7 @@ enum HF_S {
HF_DVBC_8MHZ, HF_DVBC
};
struct SStandardParam m_StandardTable[] = {
static struct SStandardParam m_StandardTable[] = {
{ 0, 0, 0x00, 0x00 }, /* HF_None */
{ 6000000, 7000000, 0x1D, 0x2C }, /* HF_B, */
{ 6900000, 8000000, 0x1E, 0x2C }, /* HF_DK, */
@ -27,7 +27,7 @@ struct SStandardParam m_StandardTable[] = {
{ 0, 0, 0x00, 0x00 }, /* HF_DVBC (Unused) */
};
struct SMap m_BP_Filter_Map[] = {
static struct SMap m_BP_Filter_Map[] = {
{ 62000000, 0x00 },
{ 84000000, 0x01 },
{ 100000000, 0x02 },
@ -799,14 +799,14 @@ static struct SRFBandMap m_RF_Band_Map[7] = {
{ 865000000, 489500000, 697500000, 842000000},
};
u8 m_Thermometer_Map_1[16] = {
static u8 m_Thermometer_Map_1[16] = {
60, 62, 66, 64,
74, 72, 68, 70,
90, 88, 84, 86,
76, 78, 82, 80,
};
u8 m_Thermometer_Map_2[16] = {
static u8 m_Thermometer_Map_2[16] = {
92, 94, 98, 96,
106, 104, 100, 102,
122, 120, 116, 118,

View file

@ -19,17 +19,14 @@
static int tda8261_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
struct dvb_frontend_ops *frontend_ops = NULL;
struct dvb_tuner_ops *tuner_ops = NULL;
struct dvb_frontend_ops *frontend_ops = &fe->ops;
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state t_state;
int err = 0;
if (&fe->ops)
frontend_ops = &fe->ops;
if (&frontend_ops->tuner_ops)
tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->get_state) {
if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
if (err < 0) {
printk("%s: Invalid parameter\n", __func__);
return err;
}
@ -41,18 +38,16 @@ static int tda8261_get_frequency(struct dvb_frontend *fe, u32 *frequency)
static int tda8261_set_frequency(struct dvb_frontend *fe, u32 frequency)
{
struct dvb_frontend_ops *frontend_ops = NULL;
struct dvb_tuner_ops *tuner_ops = NULL;
struct dvb_frontend_ops *frontend_ops = &fe->ops;
struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state t_state;
int err = 0;
t_state.frequency = frequency;
if (&fe->ops)
frontend_ops = &fe->ops;
if (&frontend_ops->tuner_ops)
tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->set_state) {
if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
if (err < 0) {
printk("%s: Invalid parameter\n", __func__);
return err;
}
@ -68,12 +63,9 @@ static int tda8261_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
struct tuner_state t_state;
int err = 0;
if (&fe->ops)
frontend_ops = &fe->ops;
if (&frontend_ops->tuner_ops)
tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->get_state) {
if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state);
if (err < 0) {
printk("%s: Invalid parameter\n", __func__);
return err;
}

View file

@ -551,6 +551,7 @@ config VIDEO_MT9V032
tristate "Micron MT9V032 sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
depends on MEDIA_CAMERA_SUPPORT
select REGMAP_I2C
---help---
This is a Video4Linux2 sensor-level driver for the Micron
MT9V032 752x480 CMOS sensor.

View file

@ -663,7 +663,6 @@ static int adv7180_remove(struct i2c_client *client)
if (state->irq > 0)
free_irq(client->irq, state);
v4l2_device_unregister_subdev(sd);
adv7180_exit_controls(state);
mutex_destroy(&state->mutex);
return 0;

View file

@ -2588,8 +2588,11 @@ static const struct adv7604_reg_seq adv7604_recommended_settings_hdmi[] = {
};
static const struct adv7604_reg_seq adv7611_recommended_settings_hdmi[] = {
/* ADV7611 Register Settings Recommendations Rev 1.5, May 2014 */
{ ADV7604_REG(ADV7604_PAGE_CP, 0x6c), 0x00 },
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x6f), 0x0c },
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x9b), 0x03 },
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x6f), 0x08 },
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x85), 0x1f },
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x87), 0x70 },
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0xda },
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x01 },

View file

@ -62,8 +62,8 @@ module_param(debug, int, 0644); /* debug level (0,1,2) */
/* ----------------------------------------------------------------------- */
static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
int size, int offset)
static int get_key_haup_common(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *ptoggle, int size, int offset)
{
unsigned char buf[6];
int start, range, toggle, dev, code, ircode;
@ -86,19 +86,10 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
if (!start)
/* no key pressed */
return 0;
/*
* Hauppauge remotes (black/silver) always use
* specific device ids. If we do not filter the
* device ids then messages destined for devices
* such as TVs (id=0) will get through causing
* mis-fired events.
*
* We also filter out invalid key presses which
* produce annoying debug log entries.
*/
ircode= (start << 12) | (toggle << 11) | (dev << 6) | code;
if ((ircode & 0x1fff)==0x1fff)
/* invalid key press */
/* filter out invalid key presses */
ircode = (start << 12) | (toggle << 11) | (dev << 6) | code;
if ((ircode & 0x1fff) == 0x1fff)
return 0;
if (!range)
@ -107,18 +98,20 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
dprintk(1,"ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d\n",
start, range, toggle, dev, code);
/* return key */
*ir_key = (dev << 8) | code;
*ir_raw = ircode;
*protocol = RC_TYPE_RC5;
*scancode = RC_SCANCODE_RC5(dev, code);
*ptoggle = toggle;
return 1;
}
static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_haup(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
return get_key_haup_common (ir, ir_key, ir_raw, 3, 0);
return get_key_haup_common (ir, protocol, scancode, toggle, 3, 0);
}
static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_haup_xvr(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
int ret;
unsigned char buf[1] = { 0 };
@ -133,10 +126,11 @@ static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
if (ret != 1)
return (ret < 0) ? ret : -EINVAL;
return get_key_haup_common (ir, ir_key, ir_raw, 6, 3);
return get_key_haup_common(ir, protocol, scancode, toggle, 6, 3);
}
static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_pixelview(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
unsigned char b;
@ -145,12 +139,15 @@ static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
dprintk(1,"read error\n");
return -EIO;
}
*ir_key = b;
*ir_raw = b;
*protocol = RC_TYPE_OTHER;
*scancode = b;
*toggle = 0;
return 1;
}
static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_fusionhdtv(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
unsigned char buf[4];
@ -168,13 +165,14 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
if(buf[0] != 0x1 || buf[1] != 0xfe)
return 0;
*ir_key = buf[2];
*ir_raw = (buf[2] << 8) | buf[3];
*protocol = RC_TYPE_UNKNOWN;
*scancode = buf[2];
*toggle = 0;
return 1;
}
static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_knc1(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
unsigned char b;
@ -197,13 +195,14 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
/* keep old data */
return 1;
*ir_key = b;
*ir_raw = b;
*protocol = RC_TYPE_UNKNOWN;
*scancode = b;
*toggle = 0;
return 1;
}
static int get_key_avermedia_cardbus(struct IR_i2c *ir,
u32 *ir_key, u32 *ir_raw)
static int get_key_avermedia_cardbus(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
unsigned char subaddr, key, keygroup;
struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0,
@ -237,12 +236,11 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
}
key |= (keygroup & 1) << 6;
*ir_key = key;
*ir_raw = key;
if (!strcmp(ir->ir_codes, RC_MAP_AVERMEDIA_M733A_RM_K6)) {
*ir_key |= keygroup << 8;
*ir_raw |= keygroup << 8;
}
*protocol = RC_TYPE_UNKNOWN;
*scancode = key;
if (ir->c->addr == 0x41) /* AVerMedia EM78P153 */
*scancode |= keygroup << 8;
*toggle = 0;
return 1;
}
@ -250,19 +248,22 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
static int ir_key_poll(struct IR_i2c *ir)
{
static u32 ir_key, ir_raw;
enum rc_type protocol;
u32 scancode;
u8 toggle;
int rc;
dprintk(3, "%s\n", __func__);
rc = ir->get_key(ir, &ir_key, &ir_raw);
rc = ir->get_key(ir, &protocol, &scancode, &toggle);
if (rc < 0) {
dprintk(2,"error\n");
return rc;
}
if (rc) {
dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key);
rc_keydown(ir->rc, ir_key, 0);
dprintk(1, "%s: proto = 0x%04x, scancode = 0x%08x\n",
__func__, protocol, scancode);
rc_keydown(ir->rc, protocol, scancode, toggle);
}
return 0;
}
@ -327,7 +328,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
case 0x6b:
name = "FusionHDTV";
ir->get_key = get_key_fusionhdtv;
rc_type = RC_BIT_RC5;
rc_type = RC_BIT_UNKNOWN;
ir_codes = RC_MAP_FUSIONHDTV_MCE;
break;
case 0x40:
@ -431,8 +432,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_set_allowed_protocols(rc, rc_type);
rc_set_enabled_protocols(rc, rc_type);
rc->allowed_protocols = rc_type;
rc->enabled_protocols = rc_type;
if (!rc->driver_name)
rc->driver_name = MODULE_NAME;

View file

@ -1,5 +1,5 @@
/*
* Driver for MT9V032 CMOS Image Sensor from Micron
* Driver for MT9V022, MT9V024, MT9V032, and MT9V034 CMOS Image Sensors
*
* Copyright (C) 2010, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
*
@ -17,6 +17,7 @@
#include <linux/i2c.h>
#include <linux/log2.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <linux/v4l2-mediabus.h>
@ -87,6 +88,7 @@
#define MT9V032_READ_MODE_COLUMN_FLIP (1 << 5)
#define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6)
#define MT9V032_READ_MODE_DARK_ROWS (1 << 7)
#define MT9V032_READ_MODE_RESERVED 0x0300
#define MT9V032_PIXEL_OPERATION_MODE 0x0f
#define MT9V034_PIXEL_OPERATION_MODE_HDR (1 << 0)
#define MT9V034_PIXEL_OPERATION_MODE_COLOR (1 << 1)
@ -133,8 +135,12 @@
#define MT9V032_THERMAL_INFO 0xc1
enum mt9v032_model {
MT9V032_MODEL_V032_COLOR,
MT9V032_MODEL_V032_MONO,
MT9V032_MODEL_V022_COLOR, /* MT9V022IX7ATC */
MT9V032_MODEL_V022_MONO, /* MT9V022IX7ATM */
MT9V032_MODEL_V024_COLOR, /* MT9V024IA7XTC */
MT9V032_MODEL_V024_MONO, /* MT9V024IA7XTM */
MT9V032_MODEL_V032_COLOR, /* MT9V032C12STM */
MT9V032_MODEL_V032_MONO, /* MT9V032C12STC */
MT9V032_MODEL_V034_COLOR,
MT9V032_MODEL_V034_MONO,
};
@ -160,14 +166,14 @@ struct mt9v032_model_info {
};
static const struct mt9v032_model_version mt9v032_versions[] = {
{ MT9V032_CHIP_ID_REV1, "MT9V032 rev1/2" },
{ MT9V032_CHIP_ID_REV3, "MT9V032 rev3" },
{ MT9V034_CHIP_ID_REV1, "MT9V034 rev1" },
{ MT9V032_CHIP_ID_REV1, "MT9V022/MT9V032 rev1/2" },
{ MT9V032_CHIP_ID_REV3, "MT9V022/MT9V032 rev3" },
{ MT9V034_CHIP_ID_REV1, "MT9V024/MT9V034 rev1" },
};
static const struct mt9v032_model_data mt9v032_model_data[] = {
{
/* MT9V032 revisions 1/2/3 */
/* MT9V022, MT9V032 revisions 1/2/3 */
.min_row_time = 660,
.min_hblank = MT9V032_HORIZONTAL_BLANKING_MIN,
.min_vblank = MT9V032_VERTICAL_BLANKING_MIN,
@ -176,7 +182,7 @@ static const struct mt9v032_model_data mt9v032_model_data[] = {
.max_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MAX,
.pclk_reg = MT9V032_PIXEL_CLOCK,
}, {
/* MT9V034 */
/* MT9V024, MT9V034 */
.min_row_time = 690,
.min_hblank = MT9V034_HORIZONTAL_BLANKING_MIN,
.min_vblank = MT9V034_VERTICAL_BLANKING_MIN,
@ -188,6 +194,22 @@ static const struct mt9v032_model_data mt9v032_model_data[] = {
};
static const struct mt9v032_model_info mt9v032_models[] = {
[MT9V032_MODEL_V022_COLOR] = {
.data = &mt9v032_model_data[0],
.color = true,
},
[MT9V032_MODEL_V022_MONO] = {
.data = &mt9v032_model_data[0],
.color = false,
},
[MT9V032_MODEL_V024_COLOR] = {
.data = &mt9v032_model_data[1],
.color = true,
},
[MT9V032_MODEL_V024_MONO] = {
.data = &mt9v032_model_data[1],
.color = false,
},
[MT9V032_MODEL_V032_COLOR] = {
.data = &mt9v032_model_data[0],
.color = true,
@ -224,6 +246,7 @@ struct mt9v032 {
struct mutex power_lock;
int power_count;
struct regmap *regmap;
struct clk *clk;
struct mt9v032_platform_data *pdata;
@ -231,7 +254,6 @@ struct mt9v032 {
const struct mt9v032_model_version *version;
u32 sysclk;
u16 chip_control;
u16 aec_agc;
u16 hblank;
struct {
@ -245,40 +267,10 @@ static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
return container_of(sd, struct mt9v032, subdev);
}
static int mt9v032_read(struct i2c_client *client, const u8 reg)
{
s32 data = i2c_smbus_read_word_swapped(client, reg);
dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__,
data, reg);
return data;
}
static int mt9v032_write(struct i2c_client *client, const u8 reg,
const u16 data)
{
dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__,
data, reg);
return i2c_smbus_write_word_swapped(client, reg, data);
}
static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set)
{
struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
u16 value = (mt9v032->chip_control & ~clear) | set;
int ret;
ret = mt9v032_write(client, MT9V032_CHIP_CONTROL, value);
if (ret < 0)
return ret;
mt9v032->chip_control = value;
return 0;
}
static int
mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
{
struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
struct regmap *map = mt9v032->regmap;
u16 value = mt9v032->aec_agc;
int ret;
@ -287,7 +279,7 @@ mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
else
value &= ~which;
ret = mt9v032_write(client, MT9V032_AEC_AGC_ENABLE, value);
ret = regmap_write(map, MT9V032_AEC_AGC_ENABLE, value);
if (ret < 0)
return ret;
@ -298,23 +290,23 @@ mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
static int
mt9v032_update_hblank(struct mt9v032 *mt9v032)
{
struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
struct v4l2_rect *crop = &mt9v032->crop;
unsigned int min_hblank = mt9v032->model->data->min_hblank;
unsigned int hblank;
if (mt9v032->version->version == MT9V034_CHIP_ID_REV1)
min_hblank += (mt9v032->hratio - 1) * 10;
min_hblank = max_t(unsigned int, (int)mt9v032->model->data->min_row_time - crop->width,
(int)min_hblank);
min_hblank = max_t(int, mt9v032->model->data->min_row_time - crop->width,
min_hblank);
hblank = max_t(unsigned int, mt9v032->hblank, min_hblank);
return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, hblank);
return regmap_write(mt9v032->regmap, MT9V032_HORIZONTAL_BLANKING,
hblank);
}
static int mt9v032_power_on(struct mt9v032 *mt9v032)
{
struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
struct regmap *map = mt9v032->regmap;
int ret;
ret = clk_set_rate(mt9v032->clk, mt9v032->sysclk);
@ -328,15 +320,15 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032)
udelay(1);
/* Reset the chip and stop data read out */
ret = mt9v032_write(client, MT9V032_RESET, 1);
ret = regmap_write(map, MT9V032_RESET, 1);
if (ret < 0)
return ret;
ret = mt9v032_write(client, MT9V032_RESET, 0);
ret = regmap_write(map, MT9V032_RESET, 0);
if (ret < 0)
return ret;
return mt9v032_write(client, MT9V032_CHIP_CONTROL, 0);
return regmap_write(map, MT9V032_CHIP_CONTROL, 0);
}
static void mt9v032_power_off(struct mt9v032 *mt9v032)
@ -346,7 +338,7 @@ static void mt9v032_power_off(struct mt9v032 *mt9v032)
static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
{
struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
struct regmap *map = mt9v032->regmap;
int ret;
if (!on) {
@ -360,14 +352,14 @@ static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
/* Configure the pixel clock polarity */
if (mt9v032->pdata && mt9v032->pdata->clk_pol) {
ret = mt9v032_write(client, mt9v032->model->data->pclk_reg,
ret = regmap_write(map, mt9v032->model->data->pclk_reg,
MT9V032_PIXEL_CLOCK_INV_PXL_CLK);
if (ret < 0)
return ret;
}
/* Disable the noise correction algorithm and restore the controls. */
ret = mt9v032_write(client, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
ret = regmap_write(map, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
if (ret < 0)
return ret;
@ -411,38 +403,39 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
const u16 mode = MT9V032_CHIP_CONTROL_MASTER_MODE
| MT9V032_CHIP_CONTROL_DOUT_ENABLE
| MT9V032_CHIP_CONTROL_SEQUENTIAL;
struct i2c_client *client = v4l2_get_subdevdata(subdev);
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
struct v4l2_rect *crop = &mt9v032->crop;
struct regmap *map = mt9v032->regmap;
unsigned int hbin;
unsigned int vbin;
int ret;
if (!enable)
return mt9v032_set_chip_control(mt9v032, mode, 0);
return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, 0);
/* Configure the window size and row/column bin */
hbin = fls(mt9v032->hratio) - 1;
vbin = fls(mt9v032->vratio) - 1;
ret = mt9v032_write(client, MT9V032_READ_MODE,
hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT |
vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT);
ret = regmap_update_bits(map, MT9V032_READ_MODE,
~MT9V032_READ_MODE_RESERVED,
hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT |
vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT);
if (ret < 0)
return ret;
ret = mt9v032_write(client, MT9V032_COLUMN_START, crop->left);
ret = regmap_write(map, MT9V032_COLUMN_START, crop->left);
if (ret < 0)
return ret;
ret = mt9v032_write(client, MT9V032_ROW_START, crop->top);
ret = regmap_write(map, MT9V032_ROW_START, crop->top);
if (ret < 0)
return ret;
ret = mt9v032_write(client, MT9V032_WINDOW_WIDTH, crop->width);
ret = regmap_write(map, MT9V032_WINDOW_WIDTH, crop->width);
if (ret < 0)
return ret;
ret = mt9v032_write(client, MT9V032_WINDOW_HEIGHT, crop->height);
ret = regmap_write(map, MT9V032_WINDOW_HEIGHT, crop->height);
if (ret < 0)
return ret;
@ -451,7 +444,7 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
return ret;
/* Switch to master "normal" mode */
return mt9v032_set_chip_control(mt9v032, 0, mode);
return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, mode);
}
static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev,
@ -633,7 +626,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct mt9v032 *mt9v032 =
container_of(ctrl->handler, struct mt9v032, ctrls);
struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
struct regmap *map = mt9v032->regmap;
u32 freq;
u16 data;
@ -643,23 +636,23 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
ctrl->val);
case V4L2_CID_GAIN:
return mt9v032_write(client, MT9V032_ANALOG_GAIN, ctrl->val);
return regmap_write(map, MT9V032_ANALOG_GAIN, ctrl->val);
case V4L2_CID_EXPOSURE_AUTO:
return mt9v032_update_aec_agc(mt9v032, MT9V032_AEC_ENABLE,
!ctrl->val);
case V4L2_CID_EXPOSURE:
return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH,
ctrl->val);
return regmap_write(map, MT9V032_TOTAL_SHUTTER_WIDTH,
ctrl->val);
case V4L2_CID_HBLANK:
mt9v032->hblank = ctrl->val;
return mt9v032_update_hblank(mt9v032);
case V4L2_CID_VBLANK:
return mt9v032_write(client, MT9V032_VERTICAL_BLANKING,
ctrl->val);
return regmap_write(map, MT9V032_VERTICAL_BLANKING,
ctrl->val);
case V4L2_CID_PIXEL_RATE:
case V4L2_CID_LINK_FREQ:
@ -667,7 +660,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
break;
freq = mt9v032->pdata->link_freqs[mt9v032->link_freq->val];
mt9v032->pixel_rate->val64 = freq;
*mt9v032->pixel_rate->p_new.p_s64 = freq;
mt9v032->sysclk = freq;
break;
@ -696,7 +689,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
| MT9V032_TEST_PATTERN_FLIP;
break;
}
return mt9v032_write(client, MT9V032_TEST_PATTERN, data);
return regmap_write(map, MT9V032_TEST_PATTERN, data);
}
return 0;
@ -764,7 +757,7 @@ static int mt9v032_registered(struct v4l2_subdev *subdev)
struct i2c_client *client = v4l2_get_subdevdata(subdev);
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
unsigned int i;
s32 version;
u32 version;
int ret;
dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n",
@ -777,10 +770,10 @@ static int mt9v032_registered(struct v4l2_subdev *subdev)
}
/* Read and check the sensor version */
version = mt9v032_read(client, MT9V032_CHIP_VERSION);
if (version < 0) {
ret = regmap_read(mt9v032->regmap, MT9V032_CHIP_VERSION, &version);
if (ret < 0) {
dev_err(&client->dev, "Failed reading chip version\n");
return version;
return ret;
}
for (i = 0; i < ARRAY_SIZE(mt9v032_versions); ++i) {
@ -867,6 +860,13 @@ static const struct v4l2_subdev_internal_ops mt9v032_subdev_internal_ops = {
.close = mt9v032_close,
};
static const struct regmap_config mt9v032_regmap_config = {
.reg_bits = 8,
.val_bits = 16,
.max_register = 0xff,
.cache_type = REGCACHE_RBTREE,
};
/* -----------------------------------------------------------------------------
* Driver initialization and probing
*/
@ -890,6 +890,10 @@ static int mt9v032_probe(struct i2c_client *client,
if (!mt9v032)
return -ENOMEM;
mt9v032->regmap = devm_regmap_init_i2c(client, &mt9v032_regmap_config);
if (IS_ERR(mt9v032->regmap))
return PTR_ERR(mt9v032->regmap);
mt9v032->clk = devm_clk_get(&client->dev, NULL);
if (IS_ERR(mt9v032->clk))
return PTR_ERR(mt9v032->clk);
@ -931,7 +935,7 @@ static int mt9v032_probe(struct i2c_client *client,
mt9v032->pixel_rate =
v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
if (pdata && pdata->link_freqs) {
unsigned int def = 0;
@ -984,10 +988,19 @@ static int mt9v032_probe(struct i2c_client *client,
mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0);
if (ret < 0)
v4l2_ctrl_handler_free(&mt9v032->ctrls);
goto err;
mt9v032->subdev.dev = &client->dev;
ret = v4l2_async_register_subdev(&mt9v032->subdev);
if (ret < 0)
goto err;
return 0;
err:
media_entity_cleanup(&mt9v032->subdev.entity);
v4l2_ctrl_handler_free(&mt9v032->ctrls);
return ret;
}
@ -996,6 +1009,7 @@ static int mt9v032_remove(struct i2c_client *client)
struct v4l2_subdev *subdev = i2c_get_clientdata(client);
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
v4l2_async_unregister_subdev(subdev);
v4l2_ctrl_handler_free(&mt9v032->ctrls);
v4l2_device_unregister_subdev(subdev);
media_entity_cleanup(&subdev->entity);
@ -1004,6 +1018,10 @@ static int mt9v032_remove(struct i2c_client *client)
}
static const struct i2c_device_id mt9v032_id[] = {
{ "mt9v022", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_COLOR] },
{ "mt9v022m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_MONO] },
{ "mt9v024", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_COLOR] },
{ "mt9v024m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_MONO] },
{ "mt9v032", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_COLOR] },
{ "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_MONO] },
{ "mt9v034", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_COLOR] },

View file

@ -554,6 +554,7 @@ static int noon010_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
nf = noon010_try_fmt(sd, &fmt->format);
noon010_try_frame_size(&fmt->format, &size);
fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
fmt->format.field = V4L2_FIELD_NONE;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
if (fh) {

View file

@ -594,6 +594,7 @@ static int s5k4ecgx_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
pf = s5k4ecgx_try_fmt(sd, &fmt->format);
s5k4ecgx_try_frame_size(&fmt->format, &fsize);
fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
fmt->format.field = V4L2_FIELD_NONE;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
if (fh) {

View file

@ -1313,6 +1313,8 @@ static int s5k5baf_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
const struct s5k5baf_pixfmt *pixfmt;
int ret = 0;
mf->field = V4L2_FIELD_NONE;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
*v4l2_subdev_get_try_format(fh, fmt->pad) = *mf;
return 0;

View file

@ -115,6 +115,7 @@ static void s5k6a3_try_format(struct v4l2_mbus_framefmt *mf)
fmt = find_sensor_format(mf);
mf->code = fmt->code;
mf->field = V4L2_FIELD_NONE;
v4l_bound_align_image(&mf->width, S5K6A3_SENSOR_MIN_WIDTH,
S5K6A3_SENSOR_MAX_WIDTH, 0,
&mf->height, S5K6A3_SENSOR_MIN_HEIGHT,

View file

@ -297,8 +297,8 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
if (rval < 0)
return rval;
sensor->pixel_rate_parray->cur.val64 = pll->vt_pix_clk_freq_hz;
sensor->pixel_rate_csi->cur.val64 = pll->pixel_rate_csi;
*sensor->pixel_rate_parray->p_cur.p_s64 = pll->vt_pix_clk_freq_hz;
*sensor->pixel_rate_csi->p_cur.p_s64 = pll->pixel_rate_csi;
return 0;
}
@ -533,7 +533,7 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
sensor->pixel_rate_parray = v4l2_ctrl_new_std(
&sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
if (sensor->pixel_array->ctrl_handler.error) {
dev_err(&client->dev,
@ -562,7 +562,7 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
sensor->pixel_rate_csi = v4l2_ctrl_new_std(
&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
if (sensor->src->ctrl_handler.error) {
dev_err(&client->dev,
@ -1554,6 +1554,7 @@ static int __smiapp_get_format(struct v4l2_subdev *subdev,
fmt->format.code = __smiapp_get_mbus_code(subdev, fmt->pad);
fmt->format.width = r->width;
fmt->format.height = r->height;
fmt->format.field = V4L2_FIELD_NONE;
}
return 0;
@ -1687,6 +1688,7 @@ static int smiapp_set_format(struct v4l2_subdev *subdev,
fmt->format.code = __smiapp_get_mbus_code(subdev, fmt->pad);
fmt->format.width &= ~1;
fmt->format.height &= ~1;
fmt->format.field = V4L2_FIELD_NONE;
fmt->format.width =
clamp(fmt->format.width,
@ -2544,9 +2546,9 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
}
snprintf(this->sd.name,
sizeof(this->sd.name), "%s %d-%4.4x %s",
sensor->minfo.name, i2c_adapter_id(client->adapter),
client->addr, _this->name);
sizeof(this->sd.name), "%s %s %d-%4.4x",
sensor->minfo.name, _this->name,
i2c_adapter_id(client->adapter), client->addr);
this->sink_fmt.width =
sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
@ -2674,6 +2676,7 @@ static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
try_fmt->width = sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
try_fmt->height = sensor->limits[SMIAPP_LIMIT_Y_ADDR_MAX] + 1;
try_fmt->code = mbus_code;
try_fmt->field = V4L2_FIELD_NONE;
try_crop->top = 0;
try_crop->left = 0;

View file

@ -403,7 +403,7 @@ static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
if (ctrl->val <= ctrl->default_value) {
/* Pack it into 0..1 step 0.125, register values 0..8 */
unsigned long range = ctrl->default_value - ctrl->minimum;
data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
data = ((ctrl->val - (s32)ctrl->minimum) * 8 + range / 2) / range;
dev_dbg(&client->dev, "Setting gain %d\n", data);
data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
@ -413,7 +413,7 @@ static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
/* Pack it into 1.125..15 variable step, register values 9..67 */
/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
unsigned long range = ctrl->maximum - ctrl->default_value - 1;
unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
unsigned long gain = ((ctrl->val - (s32)ctrl->default_value - 1) *
111 + range / 2) / range + 9;
if (gain <= 32)
@ -434,7 +434,7 @@ static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_EXPOSURE_AUTO:
if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
unsigned long range = exp->maximum - exp->minimum;
unsigned long shutter = ((exp->val - exp->minimum) * 1048 +
unsigned long shutter = ((exp->val - (s32)exp->minimum) * 1048 +
range / 2) / range + 1;
dev_dbg(&client->dev,

View file

@ -931,6 +931,12 @@ static int mt9m111_probe(struct i2c_client *client,
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
int ret;
if (client->dev.of_node) {
ssdd = devm_kzalloc(&client->dev, sizeof(*ssdd), GFP_KERNEL);
if (!ssdd)
return -ENOMEM;
client->dev.platform_data = ssdd;
}
if (!ssdd) {
dev_err(&client->dev, "mt9m111: driver needs platform data\n");
return -EINVAL;
@ -1015,6 +1021,11 @@ static int mt9m111_remove(struct i2c_client *client)
return 0;
}
static const struct of_device_id mt9m111_of_match[] = {
{ .compatible = "micron,mt9m111", },
{},
};
MODULE_DEVICE_TABLE(of, mt9m111_of_match);
static const struct i2c_device_id mt9m111_id[] = {
{ "mt9m111", 0 },
@ -1025,6 +1036,7 @@ MODULE_DEVICE_TABLE(i2c, mt9m111_id);
static struct i2c_driver mt9m111_i2c_driver = {
.driver = {
.name = "mt9m111",
.of_match_table = of_match_ptr(mt9m111_of_match),
},
.probe = mt9m111_probe,
.remove = mt9m111_remove,

View file

@ -474,7 +474,7 @@ static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl)
if (ctrl->val <= ctrl->default_value) {
/* Pack it into 0..1 step 0.125, register values 0..8 */
unsigned long range = ctrl->default_value - ctrl->minimum;
data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
data = ((ctrl->val - (s32)ctrl->minimum) * 8 + range / 2) / range;
dev_dbg(&client->dev, "Setting gain %d\n", data);
data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
@ -485,7 +485,7 @@ static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl)
/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
unsigned long range = ctrl->maximum - ctrl->default_value - 1;
/* calculated gain: map 65..127 to 9..1024 step 0.125 */
unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
unsigned long gain = ((ctrl->val - (s32)ctrl->default_value - 1) *
1015 + range / 2) / range + 9;
if (gain <= 32) /* calculated gain 9..32 -> 9..32 */
@ -507,7 +507,7 @@ static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_EXPOSURE_AUTO:
if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
unsigned int range = exp->maximum - exp->minimum;
unsigned int shutter = ((exp->val - exp->minimum) * 1048 +
unsigned int shutter = ((exp->val - (s32)exp->minimum) * 1048 +
range / 2) / range + 1;
u32 old;

View file

@ -583,7 +583,7 @@ static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
/* mt9v022 has minimum == default */
unsigned long range = gain->maximum - gain->minimum;
/* Valid values 16 to 64, 32 to 64 must be even. */
unsigned long gain_val = ((gain->val - gain->minimum) *
unsigned long gain_val = ((gain->val - (s32)gain->minimum) *
48 + range / 2) / range + 16;
if (gain_val >= 32)
@ -608,7 +608,7 @@ static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
} else {
struct v4l2_ctrl *exp = mt9v022->exposure;
unsigned long range = exp->maximum - exp->minimum;
unsigned long shutter = ((exp->val - exp->minimum) *
unsigned long shutter = ((exp->val - (s32)exp->minimum) *
479 + range / 2) / range + 1;
/*

View file

@ -56,38 +56,29 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
static int tvp5150_read(struct v4l2_subdev *sd, unsigned char addr)
{
struct i2c_client *c = v4l2_get_subdevdata(sd);
unsigned char buffer[1];
int rc;
struct i2c_msg msg[] = {
{ .addr = c->addr, .flags = 0,
.buf = &addr, .len = 1 },
{ .addr = c->addr, .flags = I2C_M_RD,
.buf = buffer, .len = 1 }
};
rc = i2c_transfer(c->adapter, msg, 2);
if (rc < 0 || rc != 2) {
v4l2_err(sd, "i2c i/o error: rc == %d (should be 2)\n", rc);
return rc < 0 ? rc : -EIO;
rc = i2c_smbus_read_byte_data(c, addr);
if (rc < 0) {
v4l2_err(sd, "i2c i/o error: rc == %d\n", rc);
return rc;
}
v4l2_dbg(2, debug, sd, "tvp5150: read 0x%02x = 0x%02x\n", addr, buffer[0]);
v4l2_dbg(2, debug, sd, "tvp5150: read 0x%02x = 0x%02x\n", addr, rc);
return (buffer[0]);
return rc;
}
static inline void tvp5150_write(struct v4l2_subdev *sd, unsigned char addr,
unsigned char value)
{
struct i2c_client *c = v4l2_get_subdevdata(sd);
unsigned char buffer[2];
int rc;
buffer[0] = addr;
buffer[1] = value;
v4l2_dbg(2, debug, sd, "tvp5150: writing 0x%02x 0x%02x\n", buffer[0], buffer[1]);
if (2 != (rc = i2c_master_send(c, buffer, 2)))
v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 2)\n", rc);
v4l2_dbg(2, debug, sd, "tvp5150: writing 0x%02x 0x%02x\n", addr, value);
rc = i2c_smbus_write_byte_data(c, addr, value);
if (rc < 0)
v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d\n", rc);
}
static void dump_reg_range(struct v4l2_subdev *sd, char *s, u8 init,
@ -1148,10 +1139,10 @@ static int tvp5150_probe(struct i2c_client *c,
/* Is TVP5150A */
if (tvp5150_id[2] == 3 || tvp5150_id[3] == 0x21) {
v4l2_info(sd, "tvp%02x%02xa detected.\n",
tvp5150_id[2], tvp5150_id[3]);
tvp5150_id[0], tvp5150_id[1]);
} else {
v4l2_info(sd, "*** unknown tvp%02x%02x chip detected.\n",
tvp5150_id[2], tvp5150_id[3]);
tvp5150_id[0], tvp5150_id[1]);
v4l2_info(sd, "*** Rom ver is %d.%d\n",
tvp5150_id[2], tvp5150_id[3]);
}

View file

@ -106,8 +106,6 @@ static long media_device_enum_entities(struct media_device *mdev,
if (ent->name) {
strncpy(u_ent.name, ent->name, sizeof(u_ent.name));
u_ent.name[sizeof(u_ent.name) - 1] = '\0';
} else {
memset(u_ent.name, 0, sizeof(u_ent.name));
}
u_ent.type = ent->type;
u_ent.revision = ent->revision;

View file

@ -759,7 +759,6 @@ static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
pix->sizeimage = pix->width * pix->height;
/* Just a guess */
pix->colorspace = V4L2_COLORSPACE_SRGB;
pix->priv = 0;
return 0;
}
@ -785,7 +784,6 @@ static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format
pix->sizeimage = pix->width * pix->height;
/* Just a guess */
pix->colorspace = V4L2_COLORSPACE_SRGB;
pix->priv = 0;
return 0;
}
@ -990,7 +988,6 @@ static struct qcam *qcam_init(struct parport *port)
qcam->vdev.fops = &qcam_fops;
qcam->vdev.lock = &qcam->lock;
qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
set_bit(V4L2_FL_USE_FH_PRIO, &qcam->vdev.flags);
qcam->vdev.release = video_device_release_empty;
video_set_drvdata(&qcam->vdev, qcam);

View file

@ -761,7 +761,6 @@ static struct qcam *qcam_init(struct parport *port)
qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
qcam->vdev.release = video_device_release_empty;
qcam->vdev.ctrl_handler = &qcam->hdl;
set_bit(V4L2_FL_USE_FH_PRIO, &qcam->vdev.flags);
video_set_drvdata(&qcam->vdev, qcam);
mutex_init(&qcam->lock);

View file

@ -1091,7 +1091,6 @@ static int pms_probe(struct device *pdev, unsigned int card)
dev->vdev.release = video_device_release_empty;
dev->vdev.lock = &dev->lock;
dev->vdev.tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
video_set_drvdata(&dev->vdev, dev);
dev->std = V4L2_STD_NTSC_M;
dev->height = 240;

View file

@ -883,7 +883,6 @@ static int w9966_init(struct w9966 *cam, struct parport *port)
cam->vdev.ioctl_ops = &w9966_ioctl_ops;
cam->vdev.release = video_device_release_empty;
cam->vdev.ctrl_handler = &cam->hdl;
set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
video_set_drvdata(&cam->vdev, cam);
mutex_init(&cam->lock);

View file

@ -19,6 +19,7 @@ if MEDIA_ANALOG_TV_SUPPORT
source "drivers/media/pci/ivtv/Kconfig"
source "drivers/media/pci/zoran/Kconfig"
source "drivers/media/pci/saa7146/Kconfig"
source "drivers/media/pci/solo6x10/Kconfig"
endif
if MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT

View file

@ -24,3 +24,4 @@ obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
obj-$(CONFIG_VIDEO_MEYE) += meye/
obj-$(CONFIG_STA2X11_VIP) += sta2x11/
obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/

View file

@ -3886,7 +3886,6 @@ static struct video_device *vdev_init(struct bttv *btv,
vfd->v4l2_dev = &btv->c.v4l2_dev;
vfd->release = video_device_release;
vfd->debug = bttv_debug;
set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
video_set_drvdata(vfd, btv);
snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",

View file

@ -73,12 +73,12 @@ static void ir_handle_key(struct bttv *btv)
if ((ir->mask_keydown && (gpio & ir->mask_keydown)) ||
(ir->mask_keyup && !(gpio & ir->mask_keyup))) {
rc_keydown_notimeout(ir->dev, data, 0);
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
} else {
/* HACK: Probably, ir->mask_keydown is missing
for this board */
if (btv->c.type == BTTV_BOARD_WINFAST2000)
rc_keydown_notimeout(ir->dev, data, 0);
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
rc_keyup(ir->dev);
}
@ -103,7 +103,7 @@ static void ir_enltv_handle_key(struct bttv *btv)
gpio, data,
(gpio & ir->mask_keyup) ? " up" : "up/down");
rc_keydown_notimeout(ir->dev, data, 0);
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
if (keyup)
rc_keyup(ir->dev);
} else {
@ -117,7 +117,7 @@ static void ir_enltv_handle_key(struct bttv *btv)
if (keyup)
rc_keyup(ir->dev);
else
rc_keydown_notimeout(ir->dev, data, 0);
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
}
ir->last_gpio = data | keyup;
@ -154,10 +154,10 @@ static void bttv_input_timer(unsigned long data)
* testing.
*/
#define RC5_START(x) (((x) >> 12) & 3)
#define RC5_TOGGLE(x) (((x) >> 11) & 1)
#define RC5_ADDR(x) (((x) >> 6) & 31)
#define RC5_INSTR(x) ((x) & 63)
#define RC5_START(x) (((x) >> 12) & 0x03)
#define RC5_TOGGLE(x) (((x) >> 11) & 0x01)
#define RC5_ADDR(x) (((x) >> 6) & 0x1f)
#define RC5_INSTR(x) (((x) >> 0) & 0x3f)
/* decode raw bit pattern to RC5 code */
static u32 bttv_rc5_decode(unsigned int code)
@ -195,8 +195,8 @@ static void bttv_rc5_timer_end(unsigned long data)
{
struct bttv_ir *ir = (struct bttv_ir *)data;
struct timeval tv;
u32 gap;
u32 rc5 = 0;
u32 gap, rc5, scancode;
u8 toggle, command, system;
/* get time */
do_gettimeofday(&tv);
@ -221,26 +221,29 @@ static void bttv_rc5_timer_end(unsigned long data)
if (ir->last_bit < 20) {
/* ignore spurious codes (caused by light/other remotes) */
dprintk("short code: %x\n", ir->code);
} else {
ir->code = (ir->code << ir->shift_by) | 1;
rc5 = bttv_rc5_decode(ir->code);
/* two start bits? */
if (RC5_START(rc5) != ir->start) {
pr_info(DEVNAME ":"
" rc5 start bits invalid: %u\n", RC5_START(rc5));
/* right address? */
} else if (RC5_ADDR(rc5) == ir->addr) {
u32 toggle = RC5_TOGGLE(rc5);
u32 instr = RC5_INSTR(rc5);
/* Good code */
rc_keydown(ir->dev, instr, toggle);
dprintk("instruction %x, toggle %x\n",
instr, toggle);
}
return;
}
ir->code = (ir->code << ir->shift_by) | 1;
rc5 = bttv_rc5_decode(ir->code);
toggle = RC5_TOGGLE(rc5);
system = RC5_ADDR(rc5);
command = RC5_INSTR(rc5);
switch (RC5_START(rc5)) {
case 0x3:
break;
case 0x2:
command += 0x40;
break;
default:
return;
}
scancode = RC_SCANCODE_RC5(system, command);
rc_keydown(ir->dev, RC_TYPE_RC5, scancode, toggle);
dprintk("scancode %x, toggle %x\n", scancode, toggle);
}
static int bttv_rc5_irq(struct bttv *btv)
@ -310,8 +313,6 @@ static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir)
/* set timer_end for code completion */
setup_timer(&ir->timer, bttv_rc5_timer_end, (unsigned long)ir);
ir->shift_by = 1;
ir->start = 3;
ir->addr = 0x0;
ir->rc5_remote_gap = ir_rc5_remote_gap;
}
}
@ -335,7 +336,8 @@ static void bttv_ir_stop(struct bttv *btv)
* Get_key functions used by I2C remotes
*/
static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_pv951(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
unsigned char b;
@ -362,8 +364,9 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
* the device is bound to the vendor-provided RC.
*/
*ir_key = b;
*ir_raw = b;
*protocol = RC_TYPE_UNKNOWN;
*scancode = b;
*toggle = 0;
return 1;
}
@ -490,8 +493,8 @@ int bttv_input_init(struct bttv *btv)
ir->polling = 50; // ms
break;
case BTTV_BOARD_NEBULA_DIGITV:
ir_codes = RC_MAP_NEBULA;
ir->rc5_gpio = true;
ir_codes = RC_MAP_NEBULA;
ir->rc5_gpio = true;
break;
case BTTV_BOARD_MACHTV_MAGICTV:
ir_codes = RC_MAP_APAC_VIEWCOMP;
@ -514,7 +517,8 @@ int bttv_input_init(struct bttv *btv)
ir->mask_keycode);
break;
}
if (NULL == ir_codes) {
if (!ir_codes) {
dprintk("Ooops: IR config error [card=%d]\n", btv->c.type);
err = -ENODEV;
goto err_out_free;

View file

@ -133,8 +133,6 @@ struct bttv_ir {
u32 polling;
u32 last_gpio;
int shift_by;
int start; // What should RC5_START() be
int addr; // What RC5_ADDR() should be.
int rc5_remote_gap;
/* RC5 gpio */

View file

@ -48,7 +48,6 @@ static inline void snd_cx18_unlock(struct snd_cx18_card *cxsc)
mutex_unlock(&cx->serialize_lock);
}
#define CX18_ALSA_DBGFLG_WARN (1 << 0)
#define CX18_ALSA_DBGFLG_WARN (1 << 0)
#define CX18_ALSA_DBGFLG_INFO (1 << 1)

View file

@ -156,7 +156,6 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
pixfmt->height = cx->cxhdl.height;
pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
pixfmt->field = V4L2_FIELD_INTERLACED;
pixfmt->priv = 0;
if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
pixfmt->pixelformat = s->pixelformat;
pixfmt->sizeimage = s->vb_bytes_per_frame;

View file

@ -375,7 +375,6 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
s->video_dev->release = video_device_release;
s->video_dev->tvnorms = V4L2_STD_ALL;
s->video_dev->lock = &cx->serialize_lock;
set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags);
cx18_set_funcs(s->video_dev);
return 0;
}

View file

@ -31,12 +31,14 @@ config VIDEO_CX23885
select DVB_TDA10071 if MEDIA_SUBDRV_AUTOSELECT
select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT
select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT
select DVB_SI2165 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT
---help---
This is a video4linux driver for Conexant 23885 based
TV cards.

View file

@ -1266,7 +1266,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
struct cx23885_fh *fh = file->private_data;
struct cx23885_dev *dev = fh->dev;
if (UNSET == dev->tuner_type)
if (dev->tuner_type == TUNER_ABSENT)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
@ -1284,7 +1284,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
struct cx23885_fh *fh = file->private_data;
struct cx23885_dev *dev = fh->dev;
if (UNSET == dev->tuner_type)
if (dev->tuner_type == TUNER_ABSENT)
return -EINVAL;
/* Update the A/V core */
@ -1299,7 +1299,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
struct cx23885_fh *fh = file->private_data;
struct cx23885_dev *dev = fh->dev;
if (UNSET == dev->tuner_type)
if (dev->tuner_type == TUNER_ABSENT)
return -EINVAL;
f->type = V4L2_TUNER_ANALOG_TV;
f->frequency = dev->freq;
@ -1347,7 +1347,7 @@ static int vidioc_querycap(struct file *file, void *priv,
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING |
0;
if (UNSET != dev->tuner_type)
if (dev->tuner_type != TUNER_ABSENT)
cap->capabilities |= V4L2_CAP_TUNER;
return 0;

View file

@ -619,7 +619,12 @@ struct cx23885_board cx23885_boards[] = {
},
[CX23885_BOARD_HAUPPAUGE_HVR4400] = {
.name = "Hauppauge WinTV-HVR4400",
.porta = CX23885_ANALOG_VIDEO,
.portb = CX23885_MPEG_DVB,
.portc = CX23885_MPEG_DVB,
.tuner_type = TUNER_NXP_TDA18271,
.tuner_addr = 0x60, /* 0xc0 >> 1 */
.tuner_bus = 1,
},
[CX23885_BOARD_AVERMEDIA_HC81R] = {
.name = "AVerTV Hybrid Express Slim HC81R",
@ -649,7 +654,31 @@ struct cx23885_board cx23885_boards[] = {
CX25840_NONE1_CH3,
.amux = CX25840_AUDIO6,
} },
}
},
[CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2] = {
.name = "DViCO FusionHDTV DVB-T Dual Express2",
.portb = CX23885_MPEG_DVB,
.portc = CX23885_MPEG_DVB,
},
[CX23885_BOARD_HAUPPAUGE_IMPACTVCBE] = {
.name = "Hauppauge ImpactVCB-e",
.tuner_type = TUNER_ABSENT,
.porta = CX23885_ANALOG_VIDEO,
.input = {{
.type = CX23885_VMUX_COMPOSITE1,
.vmux = CX25840_VIN7_CH3 |
CX25840_VIN4_CH2 |
CX25840_VIN6_CH1,
.amux = CX25840_AUDIO7,
}, {
.type = CX23885_VMUX_SVIDEO,
.vmux = CX25840_VIN7_CH3 |
CX25840_VIN4_CH2 |
CX25840_VIN8_CH1 |
CX25840_SVIDEO_ON,
.amux = CX25840_AUDIO7,
} },
},
};
const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
@ -897,6 +926,14 @@ struct cx23885_subid cx23885_subids[] = {
.subvendor = 0x1461,
.subdevice = 0xd939,
.card = CX23885_BOARD_AVERMEDIA_HC81R,
}, {
.subvendor = 0x0070,
.subdevice = 0x7133,
.card = CX23885_BOARD_HAUPPAUGE_IMPACTVCBE,
}, {
.subvendor = 0x18ac,
.subdevice = 0xdb98,
.card = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2,
},
};
const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@ -977,6 +1014,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
case 71009:
/* WinTV-HVR1200 (PCIe, Retail, full height)
* DVB-T and basic analog */
case 71100:
/* WinTV-ImpactVCB-e (PCIe, Retail, half height)
* Basic analog */
case 71359:
/* WinTV-HVR1200 (PCIe, OEM, half height)
* DVB-T and basic analog */
@ -1137,6 +1177,7 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg)
break;
case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
/* Two identical tuners on two different i2c buses,
* we need to reset the correct gpio. */
if (port->nr == 1)
@ -1280,6 +1321,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
cx_set(GP0_IO, 0x000f000f);
break;
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
/* GPIO-0 portb xc3028 reset */
/* GPIO-1 portb zl10353 reset */
/* GPIO-2 portc xc3028 reset */
@ -1449,13 +1491,16 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
break;
case CX23885_BOARD_HAUPPAUGE_HVR4400:
/* GPIO-8 tda10071 demod reset */
/* GPIO-9 si2165 demod reset */
/* Put the parts into reset and back */
cx23885_gpio_enable(dev, GPIO_8, 1);
cx23885_gpio_clear(dev, GPIO_8);
cx23885_gpio_enable(dev, GPIO_8 | GPIO_9, 1);
cx23885_gpio_clear(dev, GPIO_8 | GPIO_9);
mdelay(100);
cx23885_gpio_set(dev, GPIO_8);
cx23885_gpio_set(dev, GPIO_8 | GPIO_9);
mdelay(100);
break;
case CX23885_BOARD_AVERMEDIA_HC81R:
cx_clear(MC417_CTL, 1);
@ -1585,6 +1630,7 @@ int cx23885_ir_init(struct cx23885_dev *dev)
ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg);
break;
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
request_module("ir-kbd-i2c");
break;
}
@ -1701,6 +1747,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1850:
case CX23885_BOARD_HAUPPAUGE_HVR1290:
case CX23885_BOARD_HAUPPAUGE_HVR4400:
case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
if (dev->i2c_bus[0].i2c_rc == 0)
hauppauge_eeprom(dev, eeprom+0xc0);
break;
@ -1720,6 +1767,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
break;
case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
@ -1799,6 +1847,9 @@ void cx23885_card_setup(struct cx23885_dev *dev)
ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
break;
case CX23885_BOARD_HAUPPAUGE_HVR1250:
case CX23885_BOARD_HAUPPAUGE_HVR1500:
@ -1807,6 +1858,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1200:
case CX23885_BOARD_HAUPPAUGE_HVR1700:
case CX23885_BOARD_HAUPPAUGE_HVR1400:
case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
case CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200:
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
@ -1835,6 +1887,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
break;
case CX23885_BOARD_HAUPPAUGE_HVR1250:
case CX23885_BOARD_HAUPPAUGE_HVR1800:
case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
case CX23885_BOARD_HAUPPAUGE_HVR1700:
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:

View file

@ -44,6 +44,7 @@
#include "tuner-xc2028.h"
#include "tuner-simple.h"
#include "dib7000p.h"
#include "dib0070.h"
#include "dibx000_common.h"
#include "zl10353.h"
#include "stv0900.h"
@ -71,6 +72,7 @@
#include "tda10071.h"
#include "a8293.h"
#include "mb86a20s.h"
#include "si2165.h"
static unsigned int debug;
@ -302,6 +304,11 @@ static struct tda18271_config hauppauge_hvr1210_tuner_config = {
.output_opt = TDA18271_OUTPUT_LT_OFF,
};
static struct tda18271_config hauppauge_hvr4400_tuner_config = {
.gate = TDA18271_GATE_DIGITAL,
.output_opt = TDA18271_OUTPUT_LT_OFF,
};
static struct tda18271_std_map hauppauge_hvr127x_std_map = {
.atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 4,
.if_lvl = 1, .rfagc_top = 0x58 },
@ -702,6 +709,12 @@ static const struct a8293_config hauppauge_a8293_config = {
.i2c_addr = 0x0b,
};
static const struct si2165_config hauppauge_hvr4400_si2165_config = {
.i2c_addr = 0x64,
.chip_mode = SI2165_MODE_PLL_XTAL,
.ref_freq_Hz = 16000000,
};
static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
{
struct cx23885_dev *dev = (struct cx23885_dev *)device;
@ -746,8 +759,108 @@ static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
return 0;
};
static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
{
struct dib7000p_ops *dib7000p_ops = fe->sec_priv;
return dib7000p_ops->set_gpio(fe, 8, 0, !onoff);
}
static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
return 0;
}
static struct dib0070_config dib7070p_dib0070_config = {
.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
.reset = dib7070_tuner_reset,
.sleep = dib7070_tuner_sleep,
.clock_khz = 12000,
.freq_offset_khz_vhf = 550,
/* .flip_chip = 1, */
};
/* DIB7070 generic */
static struct dibx000_agc_config dib7070_agc_config = {
.band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
/*
* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5,
* P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
* P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0
*/
.setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) |
(0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
.inv_gain = 600,
.time_stabiliz = 10,
.alpha_level = 0,
.thlock = 118,
.wbd_inv = 0,
.wbd_ref = 3530,
.wbd_sel = 1,
.wbd_alpha = 5,
.agc1_max = 65535,
.agc1_min = 0,
.agc2_max = 65535,
.agc2_min = 0,
.agc1_pt1 = 0,
.agc1_pt2 = 40,
.agc1_pt3 = 183,
.agc1_slope1 = 206,
.agc1_slope2 = 255,
.agc2_pt1 = 72,
.agc2_pt2 = 152,
.agc2_slope1 = 88,
.agc2_slope2 = 90,
.alpha_mant = 17,
.alpha_exp = 27,
.beta_mant = 23,
.beta_exp = 51,
.perform_agc_softsplit = 0,
};
static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
.internal = 60000,
.sampling = 15000,
.pll_prediv = 1,
.pll_ratio = 20,
.pll_range = 3,
.pll_reset = 1,
.pll_bypass = 0,
.enable_refdiv = 0,
.bypclk_div = 0,
.IO_CLK_en_core = 1,
.ADClkSrc = 1,
.modulo = 2,
/* refsel, sel, freq_15k */
.sad_cfg = (3 << 14) | (1 << 12) | (524 << 0),
.ifreq = (0 << 25) | 0,
.timf = 20452225,
.xtal_hz = 12000000,
};
static struct dib7000p_config dib7070p_dib7000p_config = {
/* .output_mode = OUTMODE_MPEG2_FIFO, */
.output_mode = OUTMODE_MPEG2_SERIAL,
/* .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK, */
.output_mpeg2_in_188_bytes = 1,
.agc_config_count = 1,
.agc = &dib7070_agc_config,
.bw = &dib7070_bw_config_12_mhz,
.tuner_is_baseband = 1,
.spur_protect = 1,
.gpio_dir = 0xfcef, /* DIB7000P_GPIO_DEFAULT_DIRECTIONS, */
.gpio_val = 0x0110, /* DIB7000P_GPIO_DEFAULT_VALUES, */
.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
.hostbus_diversity = 1,
};
static int dvb_register(struct cx23885_tsport *port)
{
struct dib7000p_ops dib7000p_ops;
struct cx23885_dev *dev = port->dev;
struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL;
struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
@ -925,8 +1038,11 @@ static int dvb_register(struct cx23885_tsport *port)
break;
case CX23885_BOARD_HAUPPAUGE_HVR1400:
i2c_bus = &dev->i2c_bus[0];
fe0->dvb.frontend = dvb_attach(dib7000p_attach,
&i2c_bus->i2c_adap,
if (!dvb_attach(dib7000p_attach, &dib7000p_ops))
return -ENODEV;
fe0->dvb.frontend = dib7000p_ops.init(&i2c_bus->i2c_adap,
0x12, &hauppauge_hvr1400_dib7000_config);
if (fe0->dvb.frontend != NULL) {
struct dvb_frontend *fe;
@ -989,6 +1105,30 @@ static int dvb_register(struct cx23885_tsport *port)
}
break;
}
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2: {
i2c_bus = &dev->i2c_bus[port->nr - 1];
/* cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); */
/* cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); */
if (!dvb_attach(dib7000p_attach, &dib7000p_ops))
return -ENODEV;
if (dib7000p_ops.i2c_enumeration(&i2c_bus->i2c_adap, 1, 0x12, &dib7070p_dib7000p_config) < 0) {
printk(KERN_WARNING "Unable to enumerate dib7000p\n");
return -ENODEV;
}
fe0->dvb.frontend = dib7000p_ops.init(&i2c_bus->i2c_adap, 0x80, &dib7070p_dib7000p_config);
if (fe0->dvb.frontend != NULL) {
struct i2c_adapter *tun_i2c;
fe0->dvb.frontend->sec_priv = kmalloc(sizeof(dib7000p_ops), GFP_KERNEL);
memcpy(fe0->dvb.frontend->sec_priv, &dib7000p_ops, sizeof(dib7000p_ops));
tun_i2c = dib7000p_ops.get_i2c_master(fe0->dvb.frontend, DIBX000_I2C_INTERFACE_TUNER, 1);
if (!dvb_attach(dib0070_attach, fe0->dvb.frontend, tun_i2c, &dib7070p_dib0070_config))
return -ENODEV;
}
break;
}
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
@ -1331,13 +1471,34 @@ static int dvb_register(struct cx23885_tsport *port)
break;
case CX23885_BOARD_HAUPPAUGE_HVR4400:
i2c_bus = &dev->i2c_bus[0];
fe0->dvb.frontend = dvb_attach(tda10071_attach,
i2c_bus2 = &dev->i2c_bus[1];
switch (port->nr) {
/* port b */
case 1:
fe0->dvb.frontend = dvb_attach(tda10071_attach,
&hauppauge_tda10071_config,
&i2c_bus->i2c_adap);
if (fe0->dvb.frontend != NULL) {
dvb_attach(a8293_attach, fe0->dvb.frontend,
&i2c_bus->i2c_adap,
&hauppauge_a8293_config);
if (fe0->dvb.frontend != NULL) {
if (!dvb_attach(a8293_attach, fe0->dvb.frontend,
&i2c_bus->i2c_adap,
&hauppauge_a8293_config))
goto frontend_detach;
}
break;
/* port c */
case 2:
fe0->dvb.frontend = dvb_attach(si2165_attach,
&hauppauge_hvr4400_si2165_config,
&i2c_bus->i2c_adap);
if (fe0->dvb.frontend != NULL) {
fe0->dvb.frontend->ops.i2c_gate_ctrl = 0;
if (!dvb_attach(tda18271_attach,
fe0->dvb.frontend,
0x60, &i2c_bus2->i2c_adap,
&hauppauge_hvr4400_tuner_config))
goto frontend_detach;
}
break;
}
break;
default:

View file

@ -346,7 +346,7 @@ int cx23885_input_init(struct cx23885_dev *dev)
}
rc->dev.parent = &dev->pci->dev;
rc->driver_type = driver_type;
rc_set_allowed_protocols(rc, allowed_protos);
rc->allowed_protocols = allowed_protos;
rc->priv = kernel_ir;
rc->open = cx23885_input_ir_open;
rc->close = cx23885_input_ir_close;

View file

@ -507,6 +507,7 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
(dev->board == CX23885_BOARD_MPX885) ||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1250) ||
(dev->board == CX23885_BOARD_HAUPPAUGE_IMPACTVCBE) ||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) ||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) ||
@ -1156,7 +1157,7 @@ static int vidioc_querycap(struct file *file, void *priv,
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING |
V4L2_CAP_VBI_CAPTURE;
if (UNSET != dev->tuner_type)
if (dev->tuner_type != TUNER_ABSENT)
cap->capabilities |= V4L2_CAP_TUNER;
return 0;
}
@ -1474,7 +1475,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
{
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
if (unlikely(UNSET == dev->tuner_type))
if (dev->tuner_type == TUNER_ABSENT)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
@ -1490,7 +1491,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
{
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
if (UNSET == dev->tuner_type)
if (dev->tuner_type == TUNER_ABSENT)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
@ -1506,7 +1507,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
struct cx23885_fh *fh = priv;
struct cx23885_dev *dev = fh->dev;
if (unlikely(UNSET == dev->tuner_type))
if (dev->tuner_type == TUNER_ABSENT)
return -EINVAL;
/* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
@ -1522,7 +1523,7 @@ static int cx23885_set_freq(struct cx23885_dev *dev, const struct v4l2_frequency
{
struct v4l2_control ctrl;
if (unlikely(UNSET == dev->tuner_type))
if (dev->tuner_type == TUNER_ABSENT)
return -EINVAL;
if (unlikely(f->tuner != 0))
return -EINVAL;

View file

@ -96,6 +96,8 @@
#define CX23885_BOARD_TBS_6981 40
#define CX23885_BOARD_TBS_6980 41
#define CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200 42
#define CX23885_BOARD_HAUPPAUGE_IMPACTVCBE 43
#define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2 44
#define GPIO_0 0x00000001
#define GPIO_1 0x00000002

View file

@ -576,7 +576,6 @@ static int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.bytesperline = (chan->width * chan->fmt->depth) >> 3;
f->fmt.pix.sizeimage = chan->height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.priv = 0;
return 0;
}
@ -615,7 +614,6 @@ static int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.priv = 0;
return 0;
}
@ -867,7 +865,6 @@ static int cx25821_vidioc_try_fmt_vid_out(struct file *file, void *priv,
f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.priv = 0;
return 0;
}
@ -1109,7 +1106,6 @@ int cx25821_video_register(struct cx25821_dev *dev)
else
vdev->vfl_dir = VFL_DIR_TX;
vdev->lock = &dev->lock;
set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
snprintf(vdev->name, sizeof(vdev->name), "%s #%d", dev->name, i);
video_set_drvdata(vdev, chan);

View file

@ -1045,7 +1045,6 @@ struct video_device *cx88_vdev_init(struct cx88_core *core,
vfd->release = video_device_release;
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
core->name, type, core->board.name);
set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
return vfd;
}

View file

@ -130,25 +130,41 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
data = (data << 4) | ((gpio_key & 0xf0) >> 4);
rc_keydown(ir->dev, data, 0);
rc_keydown(ir->dev, RC_TYPE_UNKNOWN, data, 0);
} else if (ir->core->boardnr == CX88_BOARD_PROLINK_PLAYTVPVR ||
ir->core->boardnr == CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO) {
/* bit cleared on keydown, NEC scancode, 0xAAAACC, A = 0x866b */
u16 addr;
u8 cmd;
u32 scancode;
addr = (data >> 8) & 0xffff;
cmd = (data >> 0) & 0x00ff;
scancode = RC_SCANCODE_NECX(addr, cmd);
if (0 == (gpio & ir->mask_keyup))
rc_keydown_notimeout(ir->dev, RC_TYPE_NEC, scancode, 0);
else
rc_keyup(ir->dev);
} else if (ir->mask_keydown) {
/* bit set on keydown */
if (gpio & ir->mask_keydown)
rc_keydown_notimeout(ir->dev, data, 0);
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
else
rc_keyup(ir->dev);
} else if (ir->mask_keyup) {
/* bit cleared on keydown */
if (0 == (gpio & ir->mask_keyup))
rc_keydown_notimeout(ir->dev, data, 0);
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
else
rc_keyup(ir->dev);
} else {
/* can't distinguish keydown/up :-/ */
rc_keydown_notimeout(ir->dev, data, 0);
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
rc_keyup(ir->dev);
}
}
@ -329,6 +345,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
* 002-T mini RC, provided with newer PV hardware
*/
ir_codes = RC_MAP_PIXELVIEW_MK12;
rc_type = RC_BIT_NEC;
ir->gpio_addr = MO_GP1_IO;
ir->mask_keyup = 0x80;
ir->polling = 10; /* ms */
@ -416,7 +433,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
break;
case CX88_BOARD_TWINHAN_VP1027_DVBS:
ir_codes = RC_MAP_TWINHAN_VP1027_DVBS;
rc_type = RC_BIT_NEC;
ir->sampling = 0xff00; /* address */
break;
}
@ -462,14 +478,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
dev->priv = core;
dev->open = cx88_ir_open;
dev->close = cx88_ir_close;
dev->scanmask = hardware_mask;
dev->scancode_mask = hardware_mask;
if (ir->sampling) {
dev->driver_type = RC_DRIVER_IR_RAW;
dev->timeout = 10 * 1000 * 1000; /* 10 ms */
} else {
dev->driver_type = RC_DRIVER_SCANCODE;
rc_set_allowed_protocols(dev, rc_type);
dev->allowed_protocols = rc_type;
}
ir->core = core;
@ -539,7 +555,8 @@ void cx88_ir_irq(struct cx88_core *core)
ir_raw_event_handle(ir->dev);
}
static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_pvr2000(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
int flags, code;
@ -563,8 +580,9 @@ static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
dprintk("IR Key/Flags: (0x%02x/0x%02x)\n",
code & 0xff, flags & 0xff);
*ir_key = code & 0xff;
*ir_raw = code;
*protocol = RC_TYPE_UNKNOWN;
*scancode = code & 0xff;
*toggle = 0;
return 1;
}

View file

@ -1663,11 +1663,40 @@ static struct ddb_info ddb_octopus_le = {
.port_num = 2,
};
static struct ddb_info ddb_octopus_mini = {
.type = DDB_OCTOPUS,
.name = "Digital Devices Octopus Mini",
.port_num = 4,
};
static struct ddb_info ddb_v6 = {
.type = DDB_OCTOPUS,
.name = "Digital Devices Cine S2 V6 DVB adapter",
.port_num = 3,
};
static struct ddb_info ddb_v6_5 = {
.type = DDB_OCTOPUS,
.name = "Digital Devices Cine S2 V6.5 DVB adapter",
.port_num = 4,
};
static struct ddb_info ddb_dvbct = {
.type = DDB_OCTOPUS,
.name = "Digital Devices DVBCT V6.1 DVB adapter",
.port_num = 3,
};
static struct ddb_info ddb_satixS2v3 = {
.type = DDB_OCTOPUS,
.name = "Mystique SaTiX-S2 V3 DVB adapter",
.port_num = 3,
};
static struct ddb_info ddb_octopusv3 = {
.type = DDB_OCTOPUS,
.name = "Digital Devices Octopus V3 DVB adapter",
.port_num = 4,
};
#define DDVID 0xdd01 /* Digital Devices Vendor ID */
@ -1680,8 +1709,12 @@ static const struct pci_device_id ddb_id_tbl[] = {
DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le),
DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus),
DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini),
DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6),
DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5),
DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct),
DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3),
DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3),
/* in case sub-ids got deleted in flash */
DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
{0}

View file

@ -678,7 +678,8 @@ static void dm1105_emit_key(struct work_struct *work)
data = (ircom >> 8) & 0x7f;
rc_keydown(ir->dev, data, 0);
/* FIXME: UNKNOWN because we don't generate a full NEC scancode (yet?) */
rc_keydown(ir->dev, RC_TYPE_UNKNOWN, data, 0);
}
/* work handler */

View file

@ -135,8 +135,8 @@ static int ivtv_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
/* V4L2_CID_MPEG_VIDEO_DEC_PTS and V4L2_CID_MPEG_VIDEO_DEC_FRAME
control cluster */
case V4L2_CID_MPEG_VIDEO_DEC_PTS:
return ivtv_g_pts_frame(itv, &itv->ctrl_pts->val64,
&itv->ctrl_frame->val64);
return ivtv_g_pts_frame(itv, itv->ctrl_pts->p_new.p_s64,
itv->ctrl_frame->p_new.p_s64);
}
return 0;
}

View file

@ -148,7 +148,8 @@ static const char * const hw_devicenames[] = {
"ir_video", /* IVTV_HW_I2C_IR_RX_ADAPTEC */
};
static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_adaptec(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
unsigned char keybuf[4];
@ -167,9 +168,9 @@ static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
keybuf[2] &= 0x7f;
keybuf[3] |= 0x80;
*ir_key = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24;
*ir_raw = *ir_key;
*protocol = RC_TYPE_UNKNOWN;
*scancode = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24;
*toggle = 0;
return 1;
}

View file

@ -351,7 +351,6 @@ static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
pixfmt->height = itv->cxhdl.height;
pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
pixfmt->field = V4L2_FIELD_INTERLACED;
pixfmt->priv = 0;
if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
/* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
@ -418,7 +417,6 @@ static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f
pixfmt->height = itv->main_rect.height;
pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
pixfmt->field = V4L2_FIELD_INTERLACED;
pixfmt->priv = 0;
if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
case IVTV_YUV_MODE_INTERLACED:
@ -1384,7 +1382,6 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
fb->fmt.bytesperline = fb->fmt.width;
fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
fb->fmt.field = V4L2_FIELD_INTERLACED;
fb->fmt.priv = 0;
if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
fb->fmt.bytesperline *= 2;
if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||

View file

@ -251,7 +251,6 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
v4l2_disable_ioctl(s->vdev, VIDIOC_G_TUNER);
v4l2_disable_ioctl(s->vdev, VIDIOC_S_STD);
}
set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
ivtv_set_funcs(s->vdev);
return 0;
}

View file

@ -1166,7 +1166,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
f->fmt.pix.sizeimage = f->fmt.pix.height *
f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = 0;
f->fmt.pix.priv = 0;
return 0;
}
@ -1232,7 +1231,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
f->fmt.pix.sizeimage = f->fmt.pix.height *
f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = 0;
f->fmt.pix.priv = 0;
return 0;
}
@ -1749,7 +1747,6 @@ static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
v4l2_ctrl_handler_setup(&meye.hdl);
meye.vdev->ctrl_handler = &meye.hdl;
set_bit(V4L2_FL_USE_FH_PRIO, &meye.vdev->flags);
if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
video_nr) < 0) {

View file

@ -910,7 +910,6 @@ static int AllocateRingBuffers(struct pci_dev *pci_dev,
{
dma_addr_t tmp;
u32 i, j;
int status = 0;
u32 SCListMemSize = pRingBuffer->NumBuffers
* ((Buffer2Length != 0) ? (NUM_SCATTER_GATHER_ENTRIES * 2) :
NUM_SCATTER_GATHER_ENTRIES)
@ -1010,14 +1009,12 @@ static int AllocateRingBuffers(struct pci_dev *pci_dev,
}
return status;
return 0;
}
static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer,
struct SRingBufferDescriptor *pRingBuffer)
{
int status = 0;
/* Copy pointer to scatter gather list in TSRingbuffer
structure for buffer 2
Load number of buffer
@ -1038,7 +1035,7 @@ static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer,
pIdleBuffer->Head->ngeneBuffer.Number_of_entries_1;
Cur = Cur->Next;
}
return status;
return 0;
}
static u32 RingBufferSizes[MAX_STREAM] = {

View file

@ -811,7 +811,6 @@ static struct video_device *vdev_init(struct saa7134_dev *dev,
vfd->release = video_device_release;
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
dev->name, type, saa7134_boards[dev->board].name);
set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
video_set_drvdata(vfd, dev);
return vfd;
}

View file

@ -130,7 +130,6 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
f->fmt.pix.bytesperline = 0;
f->fmt.pix.priv = 0;
return 0;
}
@ -148,7 +147,6 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
f->fmt.pix.bytesperline = 0;
f->fmt.pix.priv = 0;
return 0;
}
@ -166,7 +164,6 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
f->fmt.pix.bytesperline = 0;
f->fmt.pix.priv = 0;
return 0;
}
@ -270,7 +267,6 @@ static int empress_init(struct saa7134_dev *dev)
snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
"%s empress (%s)", dev->name,
saa7134_boards[dev->board].name);
set_bit(V4L2_FL_USE_FH_PRIO, &dev->empress_dev->flags);
v4l2_ctrl_handler_init(hdl, 21);
v4l2_ctrl_add_handler(hdl, &dev->ctrl_handler, empress_ctrl_filter);
if (dev->empress_sd)

View file

@ -83,14 +83,14 @@ static int build_key(struct saa7134_dev *dev)
if (data == ir->mask_keycode)
rc_keyup(ir->dev);
else
rc_keydown_notimeout(ir->dev, data, 0);
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
return 0;
}
if (ir->polling) {
if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
(ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
rc_keydown_notimeout(ir->dev, data, 0);
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
} else {
rc_keyup(ir->dev);
}
@ -98,7 +98,7 @@ static int build_key(struct saa7134_dev *dev)
else { /* IRQ driven mode - handle key press and release in one go */
if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
(ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
rc_keydown_notimeout(ir->dev, data, 0);
rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
rc_keyup(ir->dev);
}
}
@ -108,7 +108,8 @@ static int build_key(struct saa7134_dev *dev)
/* --------------------- Chip specific I2C key builders ----------------- */
static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_flydvb_trio(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
int gpio;
int attempt = 0;
@ -132,10 +133,6 @@ static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
if (0x40000 & ~gpio)
return 0; /* No button press */
/* No button press - only before first key pressed */
if (b == 0xFF)
return 0;
/* poll IR chip */
/* weak up the IR chip */
b = 0;
@ -158,13 +155,14 @@ static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
return -EIO;
}
*ir_key = b;
*ir_raw = b;
*protocol = RC_TYPE_UNKNOWN;
*scancode = b;
*toggle = 0;
return 1;
}
static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
u32 *ir_raw)
static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
unsigned char b;
int gpio;
@ -205,14 +203,15 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
/* Button pressed */
dprintk("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b);
*ir_key = b;
*ir_raw = b;
*protocol = RC_TYPE_UNKNOWN;
*scancode = b;
*toggle = 0;
return 1;
}
/* copied and modified from get_key_msi_tvanywhere_plus() */
static int get_key_kworld_pc150u(struct IR_i2c *ir, u32 *ir_key,
u32 *ir_raw)
static int get_key_kworld_pc150u(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
unsigned char b;
unsigned int gpio;
@ -253,12 +252,14 @@ static int get_key_kworld_pc150u(struct IR_i2c *ir, u32 *ir_key,
/* Button pressed */
dprintk("get_key_kworld_pc150u: Key = 0x%02X\n", b);
*ir_key = b;
*ir_raw = b;
*protocol = RC_TYPE_UNKNOWN;
*scancode = b;
*toggle = 0;
return 1;
}
static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_purpletv(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
unsigned char b;
@ -276,12 +277,14 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
if (b & 0x80)
return 1;
*ir_key = b;
*ir_raw = b;
*protocol = RC_TYPE_UNKNOWN;
*scancode = b;
*toggle = 0;
return 1;
}
static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_hvr1110(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
unsigned char buf[5];
@ -299,14 +302,20 @@ static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
* by preserving it into two separate readings
* buf[4] bits 0 and 1, and buf[1] and buf[2] are always
* zero.
*
* Note that the keymap which the hvr1110 uses is RC5.
*
* FIXME: start bits could maybe be used...?
*/
*ir_key = 0x1fff & ((buf[3] << 8) | (buf[4] >> 2));
*ir_raw = *ir_key;
*protocol = RC_TYPE_RC5;
*scancode = RC_SCANCODE_RC5(buf[3] & 0x1f, buf[4] >> 2);
*toggle = !!(buf[3] & 0x40);
return 1;
}
static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_beholdm6xx(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
unsigned char data[12];
u32 gpio;
@ -332,17 +341,18 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
if (data[9] != (unsigned char)(~data[8]))
return 0;
*ir_raw = ((data[10] << 16) | (data[11] << 8) | (data[9] << 0));
*ir_key = *ir_raw;
*protocol = RC_TYPE_NEC;
*scancode = RC_SCANCODE_NECX(data[11] << 8 | data[10], data[9]);
*toggle = 0;
return 1;
}
/* Common (grey or coloured) pinnacle PCTV remote handling
*
*/
static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
int parity_offset, int marker, int code_modulo)
static int get_key_pinnacle(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle, int parity_offset,
int marker, int code_modulo)
{
unsigned char b[4];
unsigned int start = 0,parity = 0,code = 0;
@ -377,11 +387,11 @@ static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
code %= code_modulo;
*ir_raw = code;
*ir_key = code;
*protocol = RC_TYPE_UNKNOWN;
*scancode = code;
*toggle = 0;
i2cdprintk("Pinnacle PCTV key %02x\n", code);
return 1;
}
@ -394,10 +404,11 @@ static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
*
* Sylvain Pasche <sylvain.pasche@gmail.com>
*/
static int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_pinnacle_grey(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff);
return get_key_pinnacle(ir, protocol, scancode, toggle, 1, 0xfe, 0xff);
}
@ -405,7 +416,8 @@ static int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
*
* Ricardo Cerqueira <v4l@cerqueira.org>
*/
static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_pinnacle_color(struct IR_i2c *ir, enum rc_type *protocol,
u32 *scancode, u8 *toggle)
{
/* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE
*
@ -413,7 +425,7 @@ static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
* codes < 128
*/
return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88);
return get_key_pinnacle(ir, protocol, scancode, toggle, 2, 0x80, 0x88);
}
void saa7134_input_irq(struct saa7134_dev *dev)

View file

@ -1235,7 +1235,6 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.priv = 0;
return 0;
}
@ -1315,7 +1314,6 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.priv = 0;
return 0;
}

View file

@ -242,16 +242,14 @@ static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed)
if (!demux->dmx.frontend)
return -EINVAL;
if (dvb) {
mutex_lock(&dvb->lock);
if (dvb->feeding++ == 0) {
/* Start transport */
ret = saa7164_dvb_start_port(port);
}
mutex_unlock(&dvb->lock);
dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
__func__, port->nr, dvb->feeding);
mutex_lock(&dvb->lock);
if (dvb->feeding++ == 0) {
/* Start transport */
ret = saa7164_dvb_start_port(port);
}
mutex_unlock(&dvb->lock);
dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
__func__, port->nr, dvb->feeding);
return ret;
}
@ -266,16 +264,14 @@ static int saa7164_dvb_stop_feed(struct dvb_demux_feed *feed)
dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
if (dvb) {
mutex_lock(&dvb->lock);
if (--dvb->feeding == 0) {
/* Stop transport */
ret = saa7164_dvb_stop_streaming(port);
}
mutex_unlock(&dvb->lock);
dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
__func__, port->nr, dvb->feeding);
mutex_lock(&dvb->lock);
if (--dvb->feeding == 0) {
/* Stop transport */
ret = saa7164_dvb_stop_streaming(port);
}
mutex_unlock(&dvb->lock);
dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
__func__, port->nr, dvb->feeding);
return ret;
}

View file

@ -0,0 +1,19 @@
config VIDEO_SOLO6X10
tristate "Bluecherry / Softlogic 6x10 capture cards (MPEG-4/H.264)"
depends on PCI && VIDEO_DEV && SND && I2C
select BITREVERSE
select FONT_SUPPORT
select FONT_8x16
select VIDEOBUF2_DMA_SG
select VIDEOBUF2_DMA_CONTIG
select SND_PCM
select FONT_8x16
---help---
This driver supports the Bluecherry H.264 and MPEG-4 hardware
compression capture cards and other Softlogic-based ones.
Following cards have been tested:
* Bluecherry BC-H16480A (PCIe, 16 port, H.264)
* Bluecherry BC-H04120A (PCIe, 4 port, H.264)
* Bluecherry BC-H04120A-MPCI (Mini-PCI, 4 port, H.264)
* Bluecherry BC-04120A (PCIe, 4 port, MPEG-4)

View file

@ -0,0 +1,5 @@
solo6x10-y := solo6x10-core.o solo6x10-i2c.o solo6x10-p2m.o solo6x10-v4l2.o \
solo6x10-tw28.o solo6x10-gpio.o solo6x10-disp.o solo6x10-enc.o \
solo6x10-v4l2-enc.o solo6x10-g723.o solo6x10-eeprom.o
obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10.o

View file

@ -0,0 +1,705 @@
/*
* Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
*
* Original author:
* Ben Collins <bcollins@ubuntu.com>
*
* Additional work by:
* John Brooks <john.brooks@bluecherry.net>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but 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.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/videodev2.h>
#include <linux/delay.h>
#include <linux/sysfs.h>
#include <linux/ktime.h>
#include <linux/slab.h>
#include "solo6x10.h"
#include "solo6x10-tw28.h"
MODULE_DESCRIPTION("Softlogic 6x10 MPEG4/H.264/G.723 CODEC V4L2/ALSA Driver");
MODULE_AUTHOR("Bluecherry <[email protected]>");
MODULE_VERSION(SOLO6X10_VERSION);
MODULE_LICENSE("GPL");
static unsigned video_nr = -1;
module_param(video_nr, uint, 0644);
MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect (default)");
static int full_eeprom; /* default is only top 64B */
module_param(full_eeprom, uint, 0644);
MODULE_PARM_DESC(full_eeprom, "Allow access to full 128B EEPROM (dangerous)");
static void solo_set_time(struct solo_dev *solo_dev)
{
struct timespec ts;
ktime_get_ts(&ts);
solo_reg_write(solo_dev, SOLO_TIMER_SEC, ts.tv_sec);
solo_reg_write(solo_dev, SOLO_TIMER_USEC, ts.tv_nsec / NSEC_PER_USEC);
}
static void solo_timer_sync(struct solo_dev *solo_dev)
{
u32 sec, usec;
struct timespec ts;
long diff;
if (solo_dev->type != SOLO_DEV_6110)
return;
if (++solo_dev->time_sync < 60)
return;
solo_dev->time_sync = 0;
sec = solo_reg_read(solo_dev, SOLO_TIMER_SEC);
usec = solo_reg_read(solo_dev, SOLO_TIMER_USEC);
ktime_get_ts(&ts);
diff = (long)ts.tv_sec - (long)sec;
diff = (diff * 1000000)
+ ((long)(ts.tv_nsec / NSEC_PER_USEC) - (long)usec);
if (diff > 1000 || diff < -1000) {
solo_set_time(solo_dev);
} else if (diff) {
long usec_lsb = solo_dev->usec_lsb;
usec_lsb -= diff / 4;
if (usec_lsb < 0)
usec_lsb = 0;
else if (usec_lsb > 255)
usec_lsb = 255;
solo_dev->usec_lsb = usec_lsb;
solo_reg_write(solo_dev, SOLO_TIMER_USEC_LSB,
solo_dev->usec_lsb);
}
}
static irqreturn_t solo_isr(int irq, void *data)
{
struct solo_dev *solo_dev = data;
u32 status;
int i;
status = solo_reg_read(solo_dev, SOLO_IRQ_STAT);
if (!status)
return IRQ_NONE;
if (status & ~solo_dev->irq_mask) {
solo_reg_write(solo_dev, SOLO_IRQ_STAT,
status & ~solo_dev->irq_mask);
status &= solo_dev->irq_mask;
}
if (status & SOLO_IRQ_PCI_ERR)
solo_p2m_error_isr(solo_dev);
for (i = 0; i < SOLO_NR_P2M; i++)
if (status & SOLO_IRQ_P2M(i))
solo_p2m_isr(solo_dev, i);
if (status & SOLO_IRQ_IIC)
solo_i2c_isr(solo_dev);
if (status & SOLO_IRQ_VIDEO_IN) {
solo_video_in_isr(solo_dev);
solo_timer_sync(solo_dev);
}
if (status & SOLO_IRQ_ENCODER)
solo_enc_v4l2_isr(solo_dev);
if (status & SOLO_IRQ_G723)
solo_g723_isr(solo_dev);
/* Clear all interrupts handled */
solo_reg_write(solo_dev, SOLO_IRQ_STAT, status);
return IRQ_HANDLED;
}
static void free_solo_dev(struct solo_dev *solo_dev)
{
struct pci_dev *pdev;
if (!solo_dev)
return;
if (solo_dev->dev.parent)
device_unregister(&solo_dev->dev);
pdev = solo_dev->pdev;
/* If we never initialized the PCI device, then nothing else
* below here needs cleanup */
if (!pdev) {
kfree(solo_dev);
return;
}
if (solo_dev->reg_base) {
/* Bring down the sub-devices first */
solo_g723_exit(solo_dev);
solo_enc_v4l2_exit(solo_dev);
solo_enc_exit(solo_dev);
solo_v4l2_exit(solo_dev);
solo_disp_exit(solo_dev);
solo_gpio_exit(solo_dev);
solo_p2m_exit(solo_dev);
solo_i2c_exit(solo_dev);
/* Now cleanup the PCI device */
solo_irq_off(solo_dev, ~0);
pci_iounmap(pdev, solo_dev->reg_base);
if (pdev->irq)
free_irq(pdev->irq, solo_dev);
}
pci_release_regions(pdev);
pci_disable_device(pdev);
v4l2_device_unregister(&solo_dev->v4l2_dev);
pci_set_drvdata(pdev, NULL);
kfree(solo_dev);
}
static ssize_t eeprom_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct solo_dev *solo_dev =
container_of(dev, struct solo_dev, dev);
unsigned short *p = (unsigned short *)buf;
int i;
if (count & 0x1)
dev_warn(dev, "EEPROM Write not aligned (truncating)\n");
if (!full_eeprom && count > 64) {
dev_warn(dev, "EEPROM Write truncated to 64 bytes\n");
count = 64;
} else if (full_eeprom && count > 128) {
dev_warn(dev, "EEPROM Write truncated to 128 bytes\n");
count = 128;
}
solo_eeprom_ewen(solo_dev, 1);
for (i = full_eeprom ? 0 : 32; i < min((int)(full_eeprom ? 64 : 32),
(int)(count / 2)); i++)
solo_eeprom_write(solo_dev, i, cpu_to_be16(p[i]));
solo_eeprom_ewen(solo_dev, 0);
return count;
}
static ssize_t eeprom_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct solo_dev *solo_dev =
container_of(dev, struct solo_dev, dev);
unsigned short *p = (unsigned short *)buf;
int count = (full_eeprom ? 128 : 64);
int i;
for (i = (full_eeprom ? 0 : 32); i < (count / 2); i++)
p[i] = be16_to_cpu(solo_eeprom_read(solo_dev, i));
return count;
}
static ssize_t p2m_timeouts_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct solo_dev *solo_dev =
container_of(dev, struct solo_dev, dev);
return sprintf(buf, "%d\n", solo_dev->p2m_timeouts);
}
static ssize_t sdram_size_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct solo_dev *solo_dev =
container_of(dev, struct solo_dev, dev);
return sprintf(buf, "%dMegs\n", solo_dev->sdram_size >> 20);
}
static ssize_t tw28xx_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct solo_dev *solo_dev =
container_of(dev, struct solo_dev, dev);
return sprintf(buf, "tw2815[%d] tw2864[%d] tw2865[%d]\n",
hweight32(solo_dev->tw2815),
hweight32(solo_dev->tw2864),
hweight32(solo_dev->tw2865));
}
static ssize_t input_map_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct solo_dev *solo_dev =
container_of(dev, struct solo_dev, dev);
unsigned int val;
char *out = buf;
val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_0);
out += sprintf(out, "Channel 0 => Input %d\n", val & 0x1f);
out += sprintf(out, "Channel 1 => Input %d\n", (val >> 5) & 0x1f);
out += sprintf(out, "Channel 2 => Input %d\n", (val >> 10) & 0x1f);
out += sprintf(out, "Channel 3 => Input %d\n", (val >> 15) & 0x1f);
out += sprintf(out, "Channel 4 => Input %d\n", (val >> 20) & 0x1f);
out += sprintf(out, "Channel 5 => Input %d\n", (val >> 25) & 0x1f);
val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_1);
out += sprintf(out, "Channel 6 => Input %d\n", val & 0x1f);
out += sprintf(out, "Channel 7 => Input %d\n", (val >> 5) & 0x1f);
out += sprintf(out, "Channel 8 => Input %d\n", (val >> 10) & 0x1f);
out += sprintf(out, "Channel 9 => Input %d\n", (val >> 15) & 0x1f);
out += sprintf(out, "Channel 10 => Input %d\n", (val >> 20) & 0x1f);
out += sprintf(out, "Channel 11 => Input %d\n", (val >> 25) & 0x1f);
val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_2);
out += sprintf(out, "Channel 12 => Input %d\n", val & 0x1f);
out += sprintf(out, "Channel 13 => Input %d\n", (val >> 5) & 0x1f);
out += sprintf(out, "Channel 14 => Input %d\n", (val >> 10) & 0x1f);
out += sprintf(out, "Channel 15 => Input %d\n", (val >> 15) & 0x1f);
out += sprintf(out, "Spot Output => Input %d\n", (val >> 20) & 0x1f);
return out - buf;
}
static ssize_t p2m_timeout_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct solo_dev *solo_dev =
container_of(dev, struct solo_dev, dev);
unsigned long ms;
int ret = kstrtoul(buf, 10, &ms);
if (ret < 0 || ms > 200)
return -EINVAL;
solo_dev->p2m_jiffies = msecs_to_jiffies(ms);
return count;
}
static ssize_t p2m_timeout_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct solo_dev *solo_dev =
container_of(dev, struct solo_dev, dev);
return sprintf(buf, "%ums\n", jiffies_to_msecs(solo_dev->p2m_jiffies));
}
static ssize_t intervals_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct solo_dev *solo_dev =
container_of(dev, struct solo_dev, dev);
char *out = buf;
int fps = solo_dev->fps;
int i;
for (i = 0; i < solo_dev->nr_chans; i++) {
out += sprintf(out, "Channel %d: %d/%d (0x%08x)\n",
i, solo_dev->v4l2_enc[i]->interval, fps,
solo_reg_read(solo_dev, SOLO_CAP_CH_INTV(i)));
}
return out - buf;
}
static ssize_t sdram_offsets_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct solo_dev *solo_dev =
container_of(dev, struct solo_dev, dev);
char *out = buf;
out += sprintf(out, "DISP: 0x%08x @ 0x%08x\n",
SOLO_DISP_EXT_ADDR,
SOLO_DISP_EXT_SIZE);
out += sprintf(out, "EOSD: 0x%08x @ 0x%08x (0x%08x * %d)\n",
SOLO_EOSD_EXT_ADDR,
SOLO_EOSD_EXT_AREA(solo_dev),
SOLO_EOSD_EXT_SIZE(solo_dev),
SOLO_EOSD_EXT_AREA(solo_dev) /
SOLO_EOSD_EXT_SIZE(solo_dev));
out += sprintf(out, "MOTI: 0x%08x @ 0x%08x\n",
SOLO_MOTION_EXT_ADDR(solo_dev),
SOLO_MOTION_EXT_SIZE);
out += sprintf(out, "G723: 0x%08x @ 0x%08x\n",
SOLO_G723_EXT_ADDR(solo_dev),
SOLO_G723_EXT_SIZE);
out += sprintf(out, "CAPT: 0x%08x @ 0x%08x (0x%08x * %d)\n",
SOLO_CAP_EXT_ADDR(solo_dev),
SOLO_CAP_EXT_SIZE(solo_dev),
SOLO_CAP_PAGE_SIZE,
SOLO_CAP_EXT_SIZE(solo_dev) / SOLO_CAP_PAGE_SIZE);
out += sprintf(out, "EREF: 0x%08x @ 0x%08x (0x%08x * %d)\n",
SOLO_EREF_EXT_ADDR(solo_dev),
SOLO_EREF_EXT_AREA(solo_dev),
SOLO_EREF_EXT_SIZE,
SOLO_EREF_EXT_AREA(solo_dev) / SOLO_EREF_EXT_SIZE);
out += sprintf(out, "MPEG: 0x%08x @ 0x%08x\n",
SOLO_MP4E_EXT_ADDR(solo_dev),
SOLO_MP4E_EXT_SIZE(solo_dev));
out += sprintf(out, "JPEG: 0x%08x @ 0x%08x\n",
SOLO_JPEG_EXT_ADDR(solo_dev),
SOLO_JPEG_EXT_SIZE(solo_dev));
return out - buf;
}
static ssize_t sdram_show(struct file *file, struct kobject *kobj,
struct bin_attribute *a, char *buf,
loff_t off, size_t count)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct solo_dev *solo_dev =
container_of(dev, struct solo_dev, dev);
const int size = solo_dev->sdram_size;
if (off >= size)
return 0;
if (off + count > size)
count = size - off;
if (solo_p2m_dma(solo_dev, 0, buf, off, count, 0, 0))
return -EIO;
return count;
}
static const struct device_attribute solo_dev_attrs[] = {
__ATTR(eeprom, 0640, eeprom_show, eeprom_store),
__ATTR(p2m_timeout, 0644, p2m_timeout_show, p2m_timeout_store),
__ATTR_RO(p2m_timeouts),
__ATTR_RO(sdram_size),
__ATTR_RO(tw28xx),
__ATTR_RO(input_map),
__ATTR_RO(intervals),
__ATTR_RO(sdram_offsets),
};
static void solo_device_release(struct device *dev)
{
/* Do nothing */
}
static int solo_sysfs_init(struct solo_dev *solo_dev)
{
struct bin_attribute *sdram_attr = &solo_dev->sdram_attr;
struct device *dev = &solo_dev->dev;
const char *driver;
int i;
if (solo_dev->type == SOLO_DEV_6110)
driver = "solo6110";
else
driver = "solo6010";
dev->release = solo_device_release;
dev->parent = &solo_dev->pdev->dev;
set_dev_node(dev, dev_to_node(&solo_dev->pdev->dev));
dev_set_name(dev, "%s-%d-%d", driver, solo_dev->vfd->num,
solo_dev->nr_chans);
if (device_register(dev)) {
dev->parent = NULL;
return -ENOMEM;
}
for (i = 0; i < ARRAY_SIZE(solo_dev_attrs); i++) {
if (device_create_file(dev, &solo_dev_attrs[i])) {
device_unregister(dev);
return -ENOMEM;
}
}
sysfs_attr_init(&sdram_attr->attr);
sdram_attr->attr.name = "sdram";
sdram_attr->attr.mode = 0440;
sdram_attr->read = sdram_show;
sdram_attr->size = solo_dev->sdram_size;
if (device_create_bin_file(dev, sdram_attr)) {
device_unregister(dev);
return -ENOMEM;
}
return 0;
}
static int solo_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct solo_dev *solo_dev;
int ret;
u8 chip_id;
solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL);
if (solo_dev == NULL)
return -ENOMEM;
if (id->driver_data == SOLO_DEV_6010)
dev_info(&pdev->dev, "Probing Softlogic 6010\n");
else
dev_info(&pdev->dev, "Probing Softlogic 6110\n");
solo_dev->type = id->driver_data;
solo_dev->pdev = pdev;
spin_lock_init(&solo_dev->reg_io_lock);
ret = v4l2_device_register(&pdev->dev, &solo_dev->v4l2_dev);
if (ret)
goto fail_probe;
/* Only for during init */
solo_dev->p2m_jiffies = msecs_to_jiffies(100);
ret = pci_enable_device(pdev);
if (ret)
goto fail_probe;
pci_set_master(pdev);
/* RETRY/TRDY Timeout disabled */
pci_write_config_byte(pdev, 0x40, 0x00);
pci_write_config_byte(pdev, 0x41, 0x00);
ret = pci_request_regions(pdev, SOLO6X10_NAME);
if (ret)
goto fail_probe;
solo_dev->reg_base = pci_ioremap_bar(pdev, 0);
if (solo_dev->reg_base == NULL) {
ret = -ENOMEM;
goto fail_probe;
}
chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) &
SOLO_CHIP_ID_MASK;
switch (chip_id) {
case 7:
solo_dev->nr_chans = 16;
solo_dev->nr_ext = 5;
break;
case 6:
solo_dev->nr_chans = 8;
solo_dev->nr_ext = 2;
break;
default:
dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, assuming 4 ch\n",
chip_id);
case 5:
solo_dev->nr_chans = 4;
solo_dev->nr_ext = 1;
}
/* Disable all interrupts to start */
solo_irq_off(solo_dev, ~0);
/* Initial global settings */
if (solo_dev->type == SOLO_DEV_6010) {
solo_dev->clock_mhz = 108;
solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT
| SOLO_SYS_CFG_INPUTDIV(25)
| SOLO_SYS_CFG_FEEDBACKDIV(solo_dev->clock_mhz * 2 - 2)
| SOLO_SYS_CFG_OUTDIV(3);
solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
} else {
u32 divq, divf;
solo_dev->clock_mhz = 135;
if (solo_dev->clock_mhz < 125) {
divq = 3;
divf = (solo_dev->clock_mhz * 4) / 3 - 1;
} else {
divq = 2;
divf = (solo_dev->clock_mhz * 2) / 3 - 1;
}
solo_reg_write(solo_dev, SOLO_PLL_CONFIG,
(1 << 20) | /* PLL_RANGE */
(8 << 15) | /* PLL_DIVR */
(divq << 12) |
(divf << 4) |
(1 << 1) /* PLL_FSEN */);
solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT;
}
solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM,
solo_dev->clock_mhz - 1);
/* PLL locking time of 1ms */
mdelay(1);
ret = request_irq(pdev->irq, solo_isr, IRQF_SHARED, SOLO6X10_NAME,
solo_dev);
if (ret)
goto fail_probe;
/* Handle this from the start */
solo_irq_on(solo_dev, SOLO_IRQ_PCI_ERR);
ret = solo_i2c_init(solo_dev);
if (ret)
goto fail_probe;
/* Setup the DMA engine */
solo_reg_write(solo_dev, SOLO_DMA_CTRL,
SOLO_DMA_CTRL_REFRESH_CYCLE(1) |
SOLO_DMA_CTRL_SDRAM_SIZE(2) |
SOLO_DMA_CTRL_SDRAM_CLK_INVERT |
SOLO_DMA_CTRL_READ_CLK_SELECT |
SOLO_DMA_CTRL_LATENCY(1));
/* Undocumented crap */
solo_reg_write(solo_dev, SOLO_DMA_CTRL1,
solo_dev->type == SOLO_DEV_6010 ? 0x100 : 0x300);
if (solo_dev->type != SOLO_DEV_6010) {
solo_dev->usec_lsb = 0x3f;
solo_set_time(solo_dev);
}
/* Disable watchdog */
solo_reg_write(solo_dev, SOLO_WATCHDOG, 0);
/* Initialize sub components */
ret = solo_p2m_init(solo_dev);
if (ret)
goto fail_probe;
ret = solo_disp_init(solo_dev);
if (ret)
goto fail_probe;
ret = solo_gpio_init(solo_dev);
if (ret)
goto fail_probe;
ret = solo_tw28_init(solo_dev);
if (ret)
goto fail_probe;
ret = solo_v4l2_init(solo_dev, video_nr);
if (ret)
goto fail_probe;
ret = solo_enc_init(solo_dev);
if (ret)
goto fail_probe;
ret = solo_enc_v4l2_init(solo_dev, video_nr);
if (ret)
goto fail_probe;
ret = solo_g723_init(solo_dev);
if (ret)
goto fail_probe;
ret = solo_sysfs_init(solo_dev);
if (ret)
goto fail_probe;
/* Now that init is over, set this lower */
solo_dev->p2m_jiffies = msecs_to_jiffies(20);
return 0;
fail_probe:
free_solo_dev(solo_dev);
return ret;
}
static void solo_pci_remove(struct pci_dev *pdev)
{
struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
struct solo_dev *solo_dev = container_of(v4l2_dev, struct solo_dev, v4l2_dev);
free_solo_dev(solo_dev);
}
static const struct pci_device_id solo_id_table[] = {
/* 6010 based cards */
{ PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010),
.driver_data = SOLO_DEV_6010 },
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_4),
.driver_data = SOLO_DEV_6010 },
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_9),
.driver_data = SOLO_DEV_6010 },
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_16),
.driver_data = SOLO_DEV_6010 },
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_4),
.driver_data = SOLO_DEV_6010 },
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_9),
.driver_data = SOLO_DEV_6010 },
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_16),
.driver_data = SOLO_DEV_6010 },
/* 6110 based cards */
{ PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6110),
.driver_data = SOLO_DEV_6110 },
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_4),
.driver_data = SOLO_DEV_6110 },
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_8),
.driver_data = SOLO_DEV_6110 },
{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16),
.driver_data = SOLO_DEV_6110 },
{0,}
};
MODULE_DEVICE_TABLE(pci, solo_id_table);
static struct pci_driver solo_pci_driver = {
.name = SOLO6X10_NAME,
.id_table = solo_id_table,
.probe = solo_pci_probe,
.remove = solo_pci_remove,
};
module_pci_driver(solo_pci_driver);

View file

@ -0,0 +1,322 @@
/*
* Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
*
* Original author:
* Ben Collins <bcollins@ubuntu.com>
*
* Additional work by:
* John Brooks <john.brooks@bluecherry.net>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but 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.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/videodev2.h>
#include <media/v4l2-ioctl.h>
#include "solo6x10.h"
#define SOLO_VCLK_DELAY 3
#define SOLO_PROGRESSIVE_VSIZE 1024
#define SOLO_MOT_THRESH_W 64
#define SOLO_MOT_THRESH_H 64
#define SOLO_MOT_THRESH_SIZE 8192
#define SOLO_MOT_THRESH_REAL (SOLO_MOT_THRESH_W * SOLO_MOT_THRESH_H)
#define SOLO_MOT_FLAG_SIZE 1024
#define SOLO_MOT_FLAG_AREA (SOLO_MOT_FLAG_SIZE * 16)
static void solo_vin_config(struct solo_dev *solo_dev)
{
solo_dev->vin_hstart = 8;
solo_dev->vin_vstart = 2;
solo_reg_write(solo_dev, SOLO_SYS_VCLK,
SOLO_VCLK_SELECT(2) |
SOLO_VCLK_VIN1415_DELAY(SOLO_VCLK_DELAY) |
SOLO_VCLK_VIN1213_DELAY(SOLO_VCLK_DELAY) |
SOLO_VCLK_VIN1011_DELAY(SOLO_VCLK_DELAY) |
SOLO_VCLK_VIN0809_DELAY(SOLO_VCLK_DELAY) |
SOLO_VCLK_VIN0607_DELAY(SOLO_VCLK_DELAY) |
SOLO_VCLK_VIN0405_DELAY(SOLO_VCLK_DELAY) |
SOLO_VCLK_VIN0203_DELAY(SOLO_VCLK_DELAY) |
SOLO_VCLK_VIN0001_DELAY(SOLO_VCLK_DELAY));
solo_reg_write(solo_dev, SOLO_VI_ACT_I_P,
SOLO_VI_H_START(solo_dev->vin_hstart) |
SOLO_VI_V_START(solo_dev->vin_vstart) |
SOLO_VI_V_STOP(solo_dev->vin_vstart +
solo_dev->video_vsize));
solo_reg_write(solo_dev, SOLO_VI_ACT_I_S,
SOLO_VI_H_START(solo_dev->vout_hstart) |
SOLO_VI_V_START(solo_dev->vout_vstart) |
SOLO_VI_V_STOP(solo_dev->vout_vstart +
solo_dev->video_vsize));
solo_reg_write(solo_dev, SOLO_VI_ACT_P,
SOLO_VI_H_START(0) |
SOLO_VI_V_START(1) |
SOLO_VI_V_STOP(SOLO_PROGRESSIVE_VSIZE));
solo_reg_write(solo_dev, SOLO_VI_CH_FORMAT,
SOLO_VI_FD_SEL_MASK(0) | SOLO_VI_PROG_MASK(0));
/* On 6110, initialize mozaic darkness stength */
if (solo_dev->type == SOLO_DEV_6010)
solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 0);
else
solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 16 << 22);
solo_reg_write(solo_dev, SOLO_VI_PAGE_SW, 2);
if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG,
SOLO_VI_PB_USER_MODE);
solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV,
SOLO_VI_PB_HSIZE(858) | SOLO_VI_PB_VSIZE(246));
solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V,
SOLO_VI_PB_VSTART(4) |
SOLO_VI_PB_VSTOP(4 + 240));
} else {
solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG,
SOLO_VI_PB_USER_MODE | SOLO_VI_PB_PAL);
solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV,
SOLO_VI_PB_HSIZE(864) | SOLO_VI_PB_VSIZE(294));
solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V,
SOLO_VI_PB_VSTART(4) |
SOLO_VI_PB_VSTOP(4 + 288));
}
solo_reg_write(solo_dev, SOLO_VI_PB_ACT_H, SOLO_VI_PB_HSTART(16) |
SOLO_VI_PB_HSTOP(16 + 720));
}
static void solo_vout_config_cursor(struct solo_dev *dev)
{
int i;
/* Load (blank) cursor bitmap mask (2bpp) */
for (i = 0; i < 20; i++)
solo_reg_write(dev, SOLO_VO_CURSOR_MASK(i), 0);
solo_reg_write(dev, SOLO_VO_CURSOR_POS, 0);
solo_reg_write(dev, SOLO_VO_CURSOR_CLR,
(0x80 << 24) | (0x80 << 16) | (0x10 << 8) | 0x80);
solo_reg_write(dev, SOLO_VO_CURSOR_CLR2, (0xe0 << 8) | 0x80);
}
static void solo_vout_config(struct solo_dev *solo_dev)
{
solo_dev->vout_hstart = 6;
solo_dev->vout_vstart = 8;
solo_reg_write(solo_dev, SOLO_VO_FMT_ENC,
solo_dev->video_type |
SOLO_VO_USER_COLOR_SET_NAV |
SOLO_VO_USER_COLOR_SET_NAH |
SOLO_VO_NA_COLOR_Y(0) |
SOLO_VO_NA_COLOR_CB(0) |
SOLO_VO_NA_COLOR_CR(0));
solo_reg_write(solo_dev, SOLO_VO_ACT_H,
SOLO_VO_H_START(solo_dev->vout_hstart) |
SOLO_VO_H_STOP(solo_dev->vout_hstart +
solo_dev->video_hsize));
solo_reg_write(solo_dev, SOLO_VO_ACT_V,
SOLO_VO_V_START(solo_dev->vout_vstart) |
SOLO_VO_V_STOP(solo_dev->vout_vstart +
solo_dev->video_vsize));
solo_reg_write(solo_dev, SOLO_VO_RANGE_HV,
SOLO_VO_H_LEN(solo_dev->video_hsize) |
SOLO_VO_V_LEN(solo_dev->video_vsize));
/* Border & background colors */
solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_COLOR,
(0xa0 << 24) | (0x88 << 16) | (0xa0 << 8) | 0x88);
solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_COLOR,
(0x10 << 24) | (0x8f << 16) | (0x10 << 8) | 0x8f);
solo_reg_write(solo_dev, SOLO_VO_BKG_COLOR,
(16 << 24) | (128 << 16) | (16 << 8) | 128);
solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON);
solo_reg_write(solo_dev, SOLO_VI_WIN_SW, 0);
solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0);
solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0);
solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, SOLO_VO_DISP_ON |
SOLO_VO_DISP_ERASE_COUNT(8) |
SOLO_VO_DISP_BASE(SOLO_DISP_EXT_ADDR));
solo_vout_config_cursor(solo_dev);
/* Enable channels we support */
solo_reg_write(solo_dev, SOLO_VI_CH_ENA,
(1 << solo_dev->nr_chans) - 1);
}
static int solo_dma_vin_region(struct solo_dev *solo_dev, u32 off,
u16 val, int reg_size)
{
u16 *buf;
const int n = 64, size = n * sizeof(*buf);
int i, ret = 0;
buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
for (i = 0; i < n; i++)
buf[i] = cpu_to_le16(val);
for (i = 0; i < reg_size; i += size) {
ret = solo_p2m_dma(solo_dev, 1, buf,
SOLO_MOTION_EXT_ADDR(solo_dev) + off + i,
size, 0, 0);
if (ret)
break;
}
kfree(buf);
return ret;
}
int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val)
{
if (ch > solo_dev->nr_chans)
return -EINVAL;
return solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
(ch * SOLO_MOT_THRESH_SIZE * 2),
val, SOLO_MOT_THRESH_SIZE);
}
int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
const u16 *thresholds)
{
const unsigned size = sizeof(u16) * 64;
u32 off = SOLO_MOT_FLAG_AREA + ch * SOLO_MOT_THRESH_SIZE * 2;
u16 *buf;
int x, y;
int ret = 0;
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
for (y = 0; y < SOLO_MOTION_SZ; y++) {
for (x = 0; x < SOLO_MOTION_SZ; x++)
buf[x] = cpu_to_le16(thresholds[y * SOLO_MOTION_SZ + x]);
ret |= solo_p2m_dma(solo_dev, 1, buf,
SOLO_MOTION_EXT_ADDR(solo_dev) + off + y * size,
size, 0, 0);
}
kfree(buf);
return ret;
}
/* First 8k is motion flag (512 bytes * 16). Following that is an 8k+8k
* threshold and working table for each channel. Atleast that's what the
* spec says. However, this code (taken from rdk) has some mystery 8k
* block right after the flag area, before the first thresh table. */
static void solo_motion_config(struct solo_dev *solo_dev)
{
int i;
for (i = 0; i < solo_dev->nr_chans; i++) {
/* Clear motion flag area */
solo_dma_vin_region(solo_dev, i * SOLO_MOT_FLAG_SIZE, 0x0000,
SOLO_MOT_FLAG_SIZE);
/* Clear working cache table */
solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
(i * SOLO_MOT_THRESH_SIZE * 2) +
SOLO_MOT_THRESH_SIZE, 0x0000,
SOLO_MOT_THRESH_SIZE);
/* Set default threshold table */
solo_set_motion_threshold(solo_dev, i, SOLO_DEF_MOT_THRESH);
}
/* Default motion settings */
solo_reg_write(solo_dev, SOLO_VI_MOT_ADR, SOLO_VI_MOTION_EN(0) |
(SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
solo_reg_write(solo_dev, SOLO_VI_MOT_CTRL,
SOLO_VI_MOTION_FRAME_COUNT(3) |
SOLO_VI_MOTION_SAMPLE_LENGTH(solo_dev->video_hsize / 16)
/* | SOLO_VI_MOTION_INTR_START_STOP */
| SOLO_VI_MOTION_SAMPLE_COUNT(10));
solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0);
solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0);
}
int solo_disp_init(struct solo_dev *solo_dev)
{
int i;
solo_dev->video_hsize = 704;
if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
solo_dev->video_vsize = 240;
solo_dev->fps = 30;
} else {
solo_dev->video_vsize = 288;
solo_dev->fps = 25;
}
solo_vin_config(solo_dev);
solo_motion_config(solo_dev);
solo_vout_config(solo_dev);
for (i = 0; i < solo_dev->nr_chans; i++)
solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 1);
return 0;
}
void solo_disp_exit(struct solo_dev *solo_dev)
{
int i;
solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, 0);
solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0);
solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0);
for (i = 0; i < solo_dev->nr_chans; i++) {
solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL0(i), 0);
solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL1(i), 0);
solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 0);
}
/* Set default border */
for (i = 0; i < 5; i++)
solo_reg_write(solo_dev, SOLO_VO_BORDER_X(i), 0);
for (i = 0; i < 5; i++)
solo_reg_write(solo_dev, SOLO_VO_BORDER_Y(i), 0);
solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_MASK, 0);
solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_MASK, 0);
solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(0), 0);
solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(0), 0);
solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(0), 0);
solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(1), 0);
solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(1), 0);
solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(1), 0);
}

View file

@ -0,0 +1,150 @@
/*
* Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
*
* Original author:
* Ben Collins <bcollins@ubuntu.com>
*
* Additional work by:
* John Brooks <john.brooks@bluecherry.net>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but 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.
*/
#include <linux/kernel.h>
#include <linux/delay.h>
#include "solo6x10.h"
/* Control */
#define EE_SHIFT_CLK 0x04
#define EE_CS 0x08
#define EE_DATA_WRITE 0x02
#define EE_DATA_READ 0x01
#define EE_ENB (0x80 | EE_CS)
#define eeprom_delay() udelay(100)
#if 0
#define eeprom_delay() solo_reg_read(solo_dev, SOLO_EEPROM_CTRL)
#define eeprom_delay() ({ \
int i, ret; \
udelay(100); \
for (i = ret = 0; i < 1000 && !ret; i++) \
ret = solo_eeprom_reg_read(solo_dev); \
})
#endif
#define ADDR_LEN 6
/* Commands */
#define EE_EWEN_CMD 4
#define EE_EWDS_CMD 4
#define EE_WRITE_CMD 5
#define EE_READ_CMD 6
#define EE_ERASE_CMD 7
static unsigned int solo_eeprom_reg_read(struct solo_dev *solo_dev)
{
return solo_reg_read(solo_dev, SOLO_EEPROM_CTRL) & EE_DATA_READ;
}
static void solo_eeprom_reg_write(struct solo_dev *solo_dev, u32 data)
{
solo_reg_write(solo_dev, SOLO_EEPROM_CTRL, data);
eeprom_delay();
}
static void solo_eeprom_cmd(struct solo_dev *solo_dev, int cmd)
{
int i;
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ACCESS_EN);
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
for (i = 4 + ADDR_LEN; i >= 0; i--) {
int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0;
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE | dataval);
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
EE_SHIFT_CLK | dataval);
}
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
}
unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en)
{
int ewen_cmd = (w_en ? 0x3f : 0) | (EE_EWEN_CMD << ADDR_LEN);
unsigned int retval = 0;
int i;
solo_eeprom_cmd(solo_dev, ewen_cmd);
for (i = 0; i < 16; i++) {
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
EE_SHIFT_CLK);
retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
}
solo_eeprom_reg_write(solo_dev, ~EE_CS);
retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
return retval;
}
unsigned short solo_eeprom_read(struct solo_dev *solo_dev, int loc)
{
int read_cmd = loc | (EE_READ_CMD << ADDR_LEN);
unsigned short retval = 0;
int i;
solo_eeprom_cmd(solo_dev, read_cmd);
for (i = 0; i < 16; i++) {
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
EE_SHIFT_CLK);
retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
}
solo_eeprom_reg_write(solo_dev, ~EE_CS);
return retval;
}
int solo_eeprom_write(struct solo_dev *solo_dev, int loc,
unsigned short data)
{
int write_cmd = loc | (EE_WRITE_CMD << ADDR_LEN);
unsigned int retval;
int i;
solo_eeprom_cmd(solo_dev, write_cmd);
for (i = 15; i >= 0; i--) {
unsigned int dataval = (data >> i) & 1;
solo_eeprom_reg_write(solo_dev, EE_ENB);
solo_eeprom_reg_write(solo_dev,
EE_ENB | (dataval << 1) | EE_SHIFT_CLK);
}
solo_eeprom_reg_write(solo_dev, EE_ENB);
solo_eeprom_reg_write(solo_dev, ~EE_CS);
solo_eeprom_reg_write(solo_dev, EE_ENB);
for (i = retval = 0; i < 10000 && !retval; i++)
retval = solo_eeprom_reg_read(solo_dev);
solo_eeprom_reg_write(solo_dev, ~EE_CS);
return !retval;
}

View file

@ -0,0 +1,340 @@
/*
* Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
*
* Original author:
* Ben Collins <bcollins@ubuntu.com>
*
* Additional work by:
* John Brooks <john.brooks@bluecherry.net>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but 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.
*/
#include <linux/kernel.h>
#include <linux/font.h>
#include <linux/bitrev.h>
#include <linux/slab.h>
#include "solo6x10.h"
#define VI_PROG_HSIZE (1280 - 16)
#define VI_PROG_VSIZE (1024 - 16)
#define IRQ_LEVEL 2
static void solo_capture_config(struct solo_dev *solo_dev)
{
unsigned long height;
unsigned long width;
void *buf;
int i;
solo_reg_write(solo_dev, SOLO_CAP_BASE,
SOLO_CAP_MAX_PAGE((SOLO_CAP_EXT_SIZE(solo_dev)
- SOLO_CAP_PAGE_SIZE) >> 16)
| SOLO_CAP_BASE_ADDR(SOLO_CAP_EXT_ADDR(solo_dev) >> 16));
/* XXX: Undocumented bits at b17 and b24 */
if (solo_dev->type == SOLO_DEV_6110) {
/* NOTE: Ref driver has (62 << 24) here as well, but it causes
* wacked out frame timing on 4-port 6110. */
solo_reg_write(solo_dev, SOLO_CAP_BTW,
(1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
SOLO_CAP_MAX_BANDWIDTH(36));
} else {
solo_reg_write(solo_dev, SOLO_CAP_BTW,
(1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
SOLO_CAP_MAX_BANDWIDTH(32));
}
/* Set scale 1, 9 dimension */
width = solo_dev->video_hsize;
height = solo_dev->video_vsize;
solo_reg_write(solo_dev, SOLO_DIM_SCALE1,
SOLO_DIM_H_MB_NUM(width / 16) |
SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
/* Set scale 2, 10 dimension */
width = solo_dev->video_hsize / 2;
height = solo_dev->video_vsize;
solo_reg_write(solo_dev, SOLO_DIM_SCALE2,
SOLO_DIM_H_MB_NUM(width / 16) |
SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
/* Set scale 3, 11 dimension */
width = solo_dev->video_hsize / 2;
height = solo_dev->video_vsize / 2;
solo_reg_write(solo_dev, SOLO_DIM_SCALE3,
SOLO_DIM_H_MB_NUM(width / 16) |
SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
/* Set scale 4, 12 dimension */
width = solo_dev->video_hsize / 3;
height = solo_dev->video_vsize / 3;
solo_reg_write(solo_dev, SOLO_DIM_SCALE4,
SOLO_DIM_H_MB_NUM(width / 16) |
SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
/* Set scale 5, 13 dimension */
width = solo_dev->video_hsize / 4;
height = solo_dev->video_vsize / 2;
solo_reg_write(solo_dev, SOLO_DIM_SCALE5,
SOLO_DIM_H_MB_NUM(width / 16) |
SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
/* Progressive */
width = VI_PROG_HSIZE;
height = VI_PROG_VSIZE;
solo_reg_write(solo_dev, SOLO_DIM_PROG,
SOLO_DIM_H_MB_NUM(width / 16) |
SOLO_DIM_V_MB_NUM_FRAME(height / 16) |
SOLO_DIM_V_MB_NUM_FIELD(height / 16));
/* Clear OSD */
solo_reg_write(solo_dev, SOLO_VE_OSD_CH, 0);
solo_reg_write(solo_dev, SOLO_VE_OSD_BASE, SOLO_EOSD_EXT_ADDR >> 16);
solo_reg_write(solo_dev, SOLO_VE_OSD_CLR,
0xF0 << 16 | 0x80 << 8 | 0x80);
if (solo_dev->type == SOLO_DEV_6010)
solo_reg_write(solo_dev, SOLO_VE_OSD_OPT,
SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
else
solo_reg_write(solo_dev, SOLO_VE_OSD_OPT, SOLO_VE_OSD_V_DOUBLE
| SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
/* Clear OSG buffer */
buf = kzalloc(SOLO_EOSD_EXT_SIZE(solo_dev), GFP_KERNEL);
if (!buf)
return;
for (i = 0; i < solo_dev->nr_chans; i++) {
solo_p2m_dma(solo_dev, 1, buf,
SOLO_EOSD_EXT_ADDR +
(SOLO_EOSD_EXT_SIZE(solo_dev) * i),
SOLO_EOSD_EXT_SIZE(solo_dev), 0, 0);
}
kfree(buf);
}
#define SOLO_OSD_WRITE_SIZE (16 * OSD_TEXT_MAX)
/* Should be called with enable_lock held */
int solo_osd_print(struct solo_enc_dev *solo_enc)
{
struct solo_dev *solo_dev = solo_enc->solo_dev;
unsigned char *str = solo_enc->osd_text;
u8 *buf = solo_enc->osd_buf;
u32 reg;
const struct font_desc *vga = find_font("VGA8x16");
const unsigned char *vga_data;
int i, j;
if (WARN_ON_ONCE(!vga))
return -ENODEV;
reg = solo_reg_read(solo_dev, SOLO_VE_OSD_CH);
if (!*str) {
/* Disable OSD on this channel */
reg &= ~(1 << solo_enc->ch);
goto out;
}
memset(buf, 0, SOLO_OSD_WRITE_SIZE);
vga_data = (const unsigned char *)vga->data;
for (i = 0; *str; i++, str++) {
for (j = 0; j < 16; j++) {
buf[(j << 1) | (i & 1) | ((i & ~1) << 4)] =
bitrev8(vga_data[(*str << 4) | j]);
}
}
solo_p2m_dma(solo_dev, 1, buf,
SOLO_EOSD_EXT_ADDR_CHAN(solo_dev, solo_enc->ch),
SOLO_OSD_WRITE_SIZE, 0, 0);
/* Enable OSD on this channel */
reg |= (1 << solo_enc->ch);
out:
solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg);
return 0;
}
/**
* Set channel Quality Profile (0-3).
*/
void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch,
unsigned int qp)
{
unsigned long flags;
unsigned int idx, reg;
if ((ch > 31) || (qp > 3))
return;
if (solo_dev->type == SOLO_DEV_6010)
return;
if (ch < 16) {
idx = 0;
reg = SOLO_VE_JPEG_QP_CH_L;
} else {
ch -= 16;
idx = 1;
reg = SOLO_VE_JPEG_QP_CH_H;
}
ch *= 2;
spin_lock_irqsave(&solo_dev->jpeg_qp_lock, flags);
solo_dev->jpeg_qp[idx] &= ~(3 << ch);
solo_dev->jpeg_qp[idx] |= (qp & 3) << ch;
solo_reg_write(solo_dev, reg, solo_dev->jpeg_qp[idx]);
spin_unlock_irqrestore(&solo_dev->jpeg_qp_lock, flags);
}
int solo_g_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch)
{
int idx;
if (solo_dev->type == SOLO_DEV_6010)
return 2;
if (WARN_ON_ONCE(ch > 31))
return 2;
if (ch < 16) {
idx = 0;
} else {
ch -= 16;
idx = 1;
}
ch *= 2;
return (solo_dev->jpeg_qp[idx] >> ch) & 3;
}
#define SOLO_QP_INIT 0xaaaaaaaa
static void solo_jpeg_config(struct solo_dev *solo_dev)
{
if (solo_dev->type == SOLO_DEV_6010) {
solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
(2 << 24) | (2 << 16) | (2 << 8) | 2);
} else {
solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
(4 << 24) | (3 << 16) | (2 << 8) | 1);
}
spin_lock_init(&solo_dev->jpeg_qp_lock);
/* Initialize Quality Profile for all channels */
solo_dev->jpeg_qp[0] = solo_dev->jpeg_qp[1] = SOLO_QP_INIT;
solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_L, SOLO_QP_INIT);
solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_H, SOLO_QP_INIT);
solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG,
(SOLO_JPEG_EXT_SIZE(solo_dev) & 0xffff0000) |
((SOLO_JPEG_EXT_ADDR(solo_dev) >> 16) & 0x0000ffff));
solo_reg_write(solo_dev, SOLO_VE_JPEG_CTRL, 0xffffffff);
if (solo_dev->type == SOLO_DEV_6110) {
solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG1,
(0 << 16) | (30 << 8) | 60);
}
}
static void solo_mp4e_config(struct solo_dev *solo_dev)
{
int i;
u32 cfg;
solo_reg_write(solo_dev, SOLO_VE_CFG0,
SOLO_VE_INTR_CTRL(IRQ_LEVEL) |
SOLO_VE_BLOCK_SIZE(SOLO_MP4E_EXT_SIZE(solo_dev) >> 16) |
SOLO_VE_BLOCK_BASE(SOLO_MP4E_EXT_ADDR(solo_dev) >> 16));
cfg = SOLO_VE_BYTE_ALIGN(2) | SOLO_VE_INSERT_INDEX
| SOLO_VE_MOTION_MODE(0);
if (solo_dev->type != SOLO_DEV_6010) {
cfg |= SOLO_VE_MPEG_SIZE_H(
(SOLO_MP4E_EXT_SIZE(solo_dev) >> 24) & 0x0f);
cfg |= SOLO_VE_JPEG_SIZE_H(
(SOLO_JPEG_EXT_SIZE(solo_dev) >> 24) & 0x0f);
}
solo_reg_write(solo_dev, SOLO_VE_CFG1, cfg);
solo_reg_write(solo_dev, SOLO_VE_WMRK_POLY, 0);
solo_reg_write(solo_dev, SOLO_VE_VMRK_INIT_KEY, 0);
solo_reg_write(solo_dev, SOLO_VE_WMRK_STRL, 0);
if (solo_dev->type == SOLO_DEV_6110)
solo_reg_write(solo_dev, SOLO_VE_WMRK_ENABLE, 0);
solo_reg_write(solo_dev, SOLO_VE_ENCRYP_POLY, 0);
solo_reg_write(solo_dev, SOLO_VE_ENCRYP_INIT, 0);
solo_reg_write(solo_dev, SOLO_VE_ATTR,
SOLO_VE_LITTLE_ENDIAN |
SOLO_COMP_ATTR_FCODE(1) |
SOLO_COMP_TIME_INC(0) |
SOLO_COMP_TIME_WIDTH(15) |
SOLO_DCT_INTERVAL(solo_dev->type == SOLO_DEV_6010 ? 9 : 10));
for (i = 0; i < solo_dev->nr_chans; i++) {
solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE(i),
(SOLO_EREF_EXT_ADDR(solo_dev) +
(i * SOLO_EREF_EXT_SIZE)) >> 16);
solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE_E(i),
(SOLO_EREF_EXT_ADDR(solo_dev) +
((i + 16) * SOLO_EREF_EXT_SIZE)) >> 16);
}
if (solo_dev->type == SOLO_DEV_6110) {
solo_reg_write(solo_dev, SOLO_VE_COMPT_MOT, 0x00040008);
} else {
for (i = 0; i < solo_dev->nr_chans; i++)
solo_reg_write(solo_dev, SOLO_VE_CH_MOT(i), 0x100);
}
}
int solo_enc_init(struct solo_dev *solo_dev)
{
int i;
solo_capture_config(solo_dev);
solo_mp4e_config(solo_dev);
solo_jpeg_config(solo_dev);
for (i = 0; i < solo_dev->nr_chans; i++) {
solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
}
return 0;
}
void solo_enc_exit(struct solo_dev *solo_dev)
{
int i;
for (i = 0; i < solo_dev->nr_chans; i++) {
solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
}
}

Some files were not shown because too many files have changed in this diff Show more