summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-06-01 05:22:37 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-06-01 05:22:37 -0300
commitf132c7131268f8f4453e59546b2c989af12687bc (patch)
tree128bda02b3b602426e003d787cb231622c73e544 /linux
parentb8991839208bf9058df16c5afdc4abe46aed454d (diff)
parentded3cfe6e3debc87d199572ce1c62204c5a37391 (diff)
downloadmediapointer-dvb-s2-f132c7131268f8f4453e59546b2c989af12687bc.tar.gz
mediapointer-dvb-s2-f132c7131268f8f4453e59546b2c989af12687bc.tar.bz2
merge: http://linuxtv.org/hg/~anttip/af9015/
From: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'linux')
-rw-r--r--linux/Documentation/video4linux/CARDLIST.cx238851
-rw-r--r--linux/Documentation/video4linux/CARDLIST.cx881
-rw-r--r--linux/drivers/media/Kconfig10
-rw-r--r--linux/drivers/media/dvb/b2c2/flexcop-misc.c20
-rw-r--r--linux/drivers/media/dvb/siano/sms-cards.c179
-rw-r--r--linux/drivers/media/dvb/siano/sms-cards.h26
-rw-r--r--linux/drivers/media/dvb/siano/smscoreapi.c333
-rw-r--r--linux/drivers/media/dvb/siano/smscoreapi.h56
-rw-r--r--linux/drivers/media/dvb/siano/smsdvb.c48
-rw-r--r--linux/drivers/media/dvb/siano/smsendian.h6
-rw-r--r--linux/drivers/media/dvb/siano/smssdio.c7
-rw-r--r--linux/drivers/media/dvb/siano/smsusb.c11
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-driver.c2
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-core.c5
-rw-r--r--linux/drivers/media/video/cx231xx/cx231xx-avcore.c17
-rw-r--r--linux/drivers/media/video/cx231xx/cx231xx-video.c26
-rw-r--r--linux/drivers/media/video/cx231xx/cx231xx.h3
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-cards.c22
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-dvb.c35
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-video.c11
-rw-r--r--linux/drivers/media/video/cx23885/cx23885.h1
-rw-r--r--linux/drivers/media/video/cx88/cx88-cards.c75
-rw-r--r--linux/drivers/media/video/cx88/cx88-dvb.c1
-rw-r--r--linux/drivers/media/video/cx88/cx88-input.c2
-rw-r--r--linux/drivers/media/video/cx88/cx88-video.c11
-rw-r--r--linux/drivers/media/video/cx88/cx88.h1
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-audio.c5
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-video.c38
-rw-r--r--linux/drivers/media/video/mt9m001.c12
-rw-r--r--linux/drivers/media/video/mt9t031.c14
-rw-r--r--linux/drivers/media/video/mt9v022.c12
-rw-r--r--linux/drivers/media/video/pxa_camera.c36
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-video.c13
-rw-r--r--linux/drivers/media/video/sh_mobile_ceu_camera.c12
-rw-r--r--linux/drivers/media/video/v4l2-common.c71
-rw-r--r--linux/drivers/media/video/vivi.c11
-rw-r--r--linux/drivers/media/video/w9968cf.c35
-rw-r--r--linux/drivers/media/video/zoran/zoran_driver.c14
-rw-r--r--linux/include/media/v4l2-common.h10
39 files changed, 882 insertions, 311 deletions
diff --git a/linux/Documentation/video4linux/CARDLIST.cx23885 b/linux/Documentation/video4linux/CARDLIST.cx23885
index 948e43610..450b8f8c3 100644
--- a/linux/Documentation/video4linux/CARDLIST.cx23885
+++ b/linux/Documentation/video4linux/CARDLIST.cx23885
@@ -20,3 +20,4 @@
19 -> Hauppauge WinTV-HVR1275 [0070:2215]
20 -> Hauppauge WinTV-HVR1255 [0070:2251]
21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295]
+ 22 -> Mygica X8506 DMB-TH [14f1:8651]
diff --git a/linux/Documentation/video4linux/CARDLIST.cx88 b/linux/Documentation/video4linux/CARDLIST.cx88
index 80527b292..89093f531 100644
--- a/linux/Documentation/video4linux/CARDLIST.cx88
+++ b/linux/Documentation/video4linux/CARDLIST.cx88
@@ -79,3 +79,4 @@
78 -> Prof 6200 DVB-S [b022:3022]
79 -> Terratec Cinergy HT PCI MKII [153b:1177]
80 -> Hauppauge WinTV-IR Only [0070:9290]
+ 81 -> Leadtek WinFast DTV1800 Hybrid [107d:6654]
diff --git a/linux/drivers/media/Kconfig b/linux/drivers/media/Kconfig
index 223c36ede..ba69beeb0 100644
--- a/linux/drivers/media/Kconfig
+++ b/linux/drivers/media/Kconfig
@@ -2,8 +2,14 @@
# Multimedia device configuration
#
-menu "Multimedia devices"
+menuconfig MEDIA_SUPPORT
+ tristate "Multimedia support"
depends on HAS_IOMEM
+ help
+ If you want to use Video for Linux, DVB for Linux, or DAB adapters,
+ enable this option and other options below.
+
+if MEDIA_SUPPORT
comment "Multimedia core support"
@@ -136,4 +142,4 @@ config USB_DABUSB
module will be called dabusb.
endif # DAB
-endmenu
+endif # MEDIA_SUPPORT
diff --git a/linux/drivers/media/dvb/b2c2/flexcop-misc.c b/linux/drivers/media/dvb/b2c2/flexcop-misc.c
index e56627d2f..f06f3a907 100644
--- a/linux/drivers/media/dvb/b2c2/flexcop-misc.c
+++ b/linux/drivers/media/dvb/b2c2/flexcop-misc.c
@@ -46,16 +46,16 @@ static const char *flexcop_revision_names[] = {
};
static const char *flexcop_device_names[] = {
- "Unknown device",
- "Air2PC/AirStar 2 DVB-T",
- "Air2PC/AirStar 2 ATSC 1st generation",
- "Air2PC/AirStar 2 ATSC 2nd generation",
- "Sky2PC/SkyStar 2 DVB-S",
- "Sky2PC/SkyStar 2 DVB-S (old version)",
- "Cable2PC/CableStar 2 DVB-C",
- "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
- "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u",
- "Sky2PC/SkyStar 2 DVB-S rev 2.8",
+ [FC_UNK] = "Unknown device",
+ [FC_CABLE] = "Cable2PC/CableStar 2 DVB-C",
+ [FC_AIR_DVBT] = "Air2PC/AirStar 2 DVB-T",
+ [FC_AIR_ATSC1] = "Air2PC/AirStar 2 ATSC 1st generation",
+ [FC_AIR_ATSC2] = "Air2PC/AirStar 2 ATSC 2nd generation",
+ [FC_AIR_ATSC3] = "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
+ [FC_SKY_REV23] = "Sky2PC/SkyStar 2 DVB-S rev 2.3 (old version)",
+ [FC_SKY_REV26] = "Sky2PC/SkyStar 2 DVB-S rev 2.6",
+ [FC_SKY_REV27] = "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u",
+ [FC_SKY_REV28] = "Sky2PC/SkyStar 2 DVB-S rev 2.8",
};
static const char *flexcop_bus_names[] = {
diff --git a/linux/drivers/media/dvb/siano/sms-cards.c b/linux/drivers/media/dvb/siano/sms-cards.c
index fda483f07..d8b15d583 100644
--- a/linux/drivers/media/dvb/siano/sms-cards.c
+++ b/linux/drivers/media/dvb/siano/sms-cards.c
@@ -85,6 +85,16 @@ static struct sms_board sms_boards[] = {
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
.lna_ctrl = -1,
},
+ [SMS1XXX_BOARD_SIANO_NICE] = {
+ /* 11 */
+ .name = "Siano Nice Digital Receiver",
+ .type = SMS_NOVA_B0,
+ },
+ [SMS1XXX_BOARD_SIANO_VENICE] = {
+ /* 12 */
+ .name = "Siano Venice Digital Receiver",
+ .type = SMS_VEGA,
+ },
};
struct sms_board *sms_get_board(int id)
@@ -94,12 +104,179 @@ struct sms_board *sms_get_board(int id)
return &sms_boards[id];
}
EXPORT_SYMBOL_GPL(sms_get_board);
+static inline void sms_gpio_assign_11xx_default_led_config(
+ struct smscore_gpio_config *pGpioConfig) {
+ pGpioConfig->Direction = SMS_GPIO_DIRECTION_OUTPUT;
+ pGpioConfig->InputCharacteristics =
+ SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL;
+ pGpioConfig->OutputDriving = SMS_GPIO_OUTPUT_DRIVING_4mA;
+ pGpioConfig->OutputSlewRate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS;
+ pGpioConfig->PullUpDown = SMS_GPIO_PULL_UP_DOWN_NONE;
+}
+
+int sms_board_event(struct smscore_device_t *coredev,
+ enum SMS_BOARD_EVENTS gevent) {
+ int board_id = smscore_get_board_id(coredev);
+ struct sms_board *board = sms_get_board(board_id);
+ struct smscore_gpio_config MyGpioConfig;
+
+ sms_gpio_assign_11xx_default_led_config(&MyGpioConfig);
+
+ switch (gevent) {
+ case BOARD_EVENT_POWER_INIT: /* including hotplug */
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ /* set I/O and turn off all LEDs */
+ smscore_gpio_configure(coredev,
+ board->board_cfg.leds_power,
+ &MyGpioConfig);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.leds_power, 0);
+ smscore_gpio_configure(coredev, board->board_cfg.led0,
+ &MyGpioConfig);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led0, 0);
+ smscore_gpio_configure(coredev, board->board_cfg.led1,
+ &MyGpioConfig);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 0);
+ break;
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
+ /* set I/O and turn off LNA */
+ smscore_gpio_configure(coredev,
+ board->board_cfg.foreign_lna0_ctrl,
+ &MyGpioConfig);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.foreign_lna0_ctrl,
+ 0);
+ break;
+ }
+ break; /* BOARD_EVENT_BIND */
+
+ case BOARD_EVENT_POWER_SUSPEND:
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.leds_power, 0);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led0, 0);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 0);
+ break;
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.foreign_lna0_ctrl,
+ 0);
+ break;
+ }
+ break; /* BOARD_EVENT_POWER_SUSPEND */
+
+ case BOARD_EVENT_POWER_RESUME:
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.leds_power, 1);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led0, 1);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 0);
+ break;
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.foreign_lna0_ctrl,
+ 1);
+ break;
+ }
+ break; /* BOARD_EVENT_POWER_RESUME */
+
+ case BOARD_EVENT_BIND:
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.leds_power, 1);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led0, 1);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 0);
+ break;
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.foreign_lna0_ctrl,
+ 1);
+ break;
+ }
+ break; /* BOARD_EVENT_BIND */
+
+ case BOARD_EVENT_SCAN_PROG:
+ break; /* BOARD_EVENT_SCAN_PROG */
+ case BOARD_EVENT_SCAN_COMP:
+ break; /* BOARD_EVENT_SCAN_COMP */
+ case BOARD_EVENT_EMERGENCY_WARNING_SIGNAL:
+ break; /* BOARD_EVENT_EMERGENCY_WARNING_SIGNAL */
+ case BOARD_EVENT_FE_LOCK:
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 1);
+ break;
+ }
+ break; /* BOARD_EVENT_FE_LOCK */
+ case BOARD_EVENT_FE_UNLOCK:
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 0);
+ break;
+ }
+ break; /* BOARD_EVENT_FE_UNLOCK */
+ case BOARD_EVENT_DEMOD_LOCK:
+ break; /* BOARD_EVENT_DEMOD_LOCK */
+ case BOARD_EVENT_DEMOD_UNLOCK:
+ break; /* BOARD_EVENT_DEMOD_UNLOCK */
+ case BOARD_EVENT_RECEPTION_MAX_4:
+ break; /* BOARD_EVENT_RECEPTION_MAX_4 */
+ case BOARD_EVENT_RECEPTION_3:
+ break; /* BOARD_EVENT_RECEPTION_3 */
+ case BOARD_EVENT_RECEPTION_2:
+ break; /* BOARD_EVENT_RECEPTION_2 */
+ case BOARD_EVENT_RECEPTION_1:
+ break; /* BOARD_EVENT_RECEPTION_1 */
+ case BOARD_EVENT_RECEPTION_LOST_0:
+ break; /* BOARD_EVENT_RECEPTION_LOST_0 */
+ case BOARD_EVENT_MULTIPLEX_OK:
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 1);
+ break;
+ }
+ break; /* BOARD_EVENT_MULTIPLEX_OK */
+ case BOARD_EVENT_MULTIPLEX_ERRORS:
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 0);
+ break;
+ }
+ break; /* BOARD_EVENT_MULTIPLEX_ERRORS */
+
+ default:
+ sms_err("Unknown SMS board event");
+ break;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(sms_board_event);
static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable)
{
int lvl, ret;
u32 gpio;
- struct smscore_gpio_config gpioconfig = {
+ struct smscore_config_gpio gpioconfig = {
.direction = SMS_GPIO_DIRECTION_OUTPUT,
.pullupdown = SMS_GPIO_PULLUPDOWN_NONE,
.inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL,
diff --git a/linux/drivers/media/dvb/siano/sms-cards.h b/linux/drivers/media/dvb/siano/sms-cards.h
index 447481ab5..38f062f6a 100644
--- a/linux/drivers/media/dvb/siano/sms-cards.h
+++ b/linux/drivers/media/dvb/siano/sms-cards.h
@@ -35,6 +35,8 @@
#define SMS1XXX_BOARD_HAUPPAUGE_WINDHAM 8
#define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD 9
#define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10
+#define SMS1XXX_BOARD_SIANO_NICE 11
+#define SMS1XXX_BOARD_SIANO_VENICE 12
struct sms_board_gpio_cfg {
int lna_vhf_exist;
@@ -83,6 +85,30 @@ struct sms_board *sms_get_board(int id);
extern struct smscore_device_t *coredev;
+enum SMS_BOARD_EVENTS {
+ BOARD_EVENT_POWER_INIT,
+ BOARD_EVENT_POWER_SUSPEND,
+ BOARD_EVENT_POWER_RESUME,
+ BOARD_EVENT_BIND,
+ BOARD_EVENT_SCAN_PROG,
+ BOARD_EVENT_SCAN_COMP,
+ BOARD_EVENT_EMERGENCY_WARNING_SIGNAL,
+ BOARD_EVENT_FE_LOCK,
+ BOARD_EVENT_FE_UNLOCK,
+ BOARD_EVENT_DEMOD_LOCK,
+ BOARD_EVENT_DEMOD_UNLOCK,
+ BOARD_EVENT_RECEPTION_MAX_4,
+ BOARD_EVENT_RECEPTION_3,
+ BOARD_EVENT_RECEPTION_2,
+ BOARD_EVENT_RECEPTION_1,
+ BOARD_EVENT_RECEPTION_LOST_0,
+ BOARD_EVENT_MULTIPLEX_OK,
+ BOARD_EVENT_MULTIPLEX_ERRORS
+};
+
+int sms_board_event(struct smscore_device_t *coredev,
+ enum SMS_BOARD_EVENTS gevent);
+
int sms_board_setup(struct smscore_device_t *coredev);
#define SMS_LED_OFF 0
diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c
index 16917016c..e513408fc 100644
--- a/linux/drivers/media/dvb/siano/smscoreapi.c
+++ b/linux/drivers/media/dvb/siano/smscoreapi.c
@@ -352,6 +352,9 @@ int smscore_register_device(struct smsdevice_params_t *params,
init_completion(&dev->init_device_done);
init_completion(&dev->reload_start_done);
init_completion(&dev->resume_done);
+ init_completion(&dev->gpio_configuration_done);
+ init_completion(&dev->gpio_set_level_done);
+ init_completion(&dev->gpio_get_level_done);
init_completion(&dev->ir_init_done);
/* Buffer management */
@@ -1051,6 +1054,23 @@ void smscore_onresponse(struct smscore_device_t *coredev,
case MSG_SMS_SLEEP_RESUME_COMP_IND:
complete(&coredev->resume_done);
break;
+ case MSG_SMS_GPIO_CONFIG_EX_RES:
+ sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES");
+ complete(&coredev->gpio_configuration_done);
+ break;
+ case MSG_SMS_GPIO_SET_LEVEL_RES:
+ sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES");
+ complete(&coredev->gpio_set_level_done);
+ break;
+ case MSG_SMS_GPIO_GET_LEVEL_RES:
+ {
+ u32 *msgdata = (u32 *) phdr;
+ coredev->gpio_get_res = msgdata[1];
+ sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d",
+ coredev->gpio_get_res);
+ complete(&coredev->gpio_get_level_done);
+ break;
+ }
case MSG_SMS_START_IR_RES:
complete(&coredev->ir_init_done);
break;
@@ -1331,8 +1351,9 @@ static int smscore_map_common_buffer(struct smscore_device_t *coredev,
}
#endif
+/* old GPIO managments implementation */
int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
- struct smscore_gpio_config *pinconfig)
+ struct smscore_config_gpio *pinconfig)
{
struct {
struct SmsMsgHdr_ST hdr;
@@ -1401,110 +1422,254 @@ int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level)
&msg, sizeof(msg));
}
-static int __init smscore_module_init(void)
-{
- int rc = 0;
+/* new GPIO managment implementation */
+static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum,
+ u32 *pGroupNum, u32 *pGroupCfg) {
+
+ *pGroupCfg = 1;
+
+ if (PinNum >= 0 && PinNum <= 1) {
+ *pTranslatedPinNum = 0;
+ *pGroupNum = 9;
+ *pGroupCfg = 2;
+ } else if (PinNum >= 2 && PinNum <= 6) {
+ *pTranslatedPinNum = 2;
+ *pGroupNum = 0;
+ *pGroupCfg = 2;
+ } else if (PinNum >= 7 && PinNum <= 11) {
+ *pTranslatedPinNum = 7;
+ *pGroupNum = 1;
+ } else if (PinNum >= 12 && PinNum <= 15) {
+ *pTranslatedPinNum = 12;
+ *pGroupNum = 2;
+ *pGroupCfg = 3;
+ } else if (PinNum == 16) {
+ *pTranslatedPinNum = 16;
+ *pGroupNum = 23;
+ } else if (PinNum >= 17 && PinNum <= 24) {
+ *pTranslatedPinNum = 17;
+ *pGroupNum = 3;
+ } else if (PinNum == 25) {
+ *pTranslatedPinNum = 25;
+ *pGroupNum = 6;
+ } else if (PinNum >= 26 && PinNum <= 28) {
+ *pTranslatedPinNum = 26;
+ *pGroupNum = 4;
+ } else if (PinNum == 29) {
+ *pTranslatedPinNum = 29;
+ *pGroupNum = 5;
+ *pGroupCfg = 2;
+ } else if (PinNum == 30) {
+ *pTranslatedPinNum = 30;
+ *pGroupNum = 8;
+ } else if (PinNum == 31) {
+ *pTranslatedPinNum = 31;
+ *pGroupNum = 17;
+ } else
+ return -1;
- INIT_LIST_HEAD(&g_smscore_notifyees);
- INIT_LIST_HEAD(&g_smscore_devices);
- kmutex_init(&g_smscore_deviceslock);
+ *pGroupCfg <<= 24;
- INIT_LIST_HEAD(&g_smscore_registry);
- kmutex_init(&g_smscore_registrylock);
+ return 0;
+}
-#if 0 /* def SMS_CHAR_CLIENT */
- /* Char interface Register */
- rc = smschar_register();
- if (rc) {
- sms_err("Error registering char device client.\n");
- goto smschar_error;
- }
-#endif
+int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
+ struct smscore_gpio_config *pGpioConfig) {
+
+ u32 totalLen;
+ u32 TranslatedPinNum;
+ u32 GroupNum;
+ u32 ElectricChar;
+ u32 groupCfg;
+ void *buffer;
+ int rc;
+
+ struct SetGpioMsg {
+ struct SmsMsgHdr_ST xMsgHeader;
+ u32 msgData[6];
+ } *pMsg;
-#if 0 /* def SMS_DVB_CLIENT */
- /* DVB Register */
- rc = smsdvb_register();
- if (rc) {
- sms_err("Error registering DVB client.\n");
- goto smsdvb_error;
- }
-#endif
-#if 0 /* def SMS_NET_CLIENT */
- /* DVB Register */
- rc = smsnet_register();
- if (rc) {
- sms_err("Error registering Network client.\n");
- goto smsnet_error;
+ if (PinNum > MAX_GPIO_PIN_NUMBER)
+ return -EINVAL;
+
+ if (pGpioConfig == NULL)
+ return -EINVAL;
+
+ totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6);
+
+ buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+ GFP_KERNEL | GFP_DMA);
+ if (!buffer)
+ return -ENOMEM;
+
+ pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+ pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+ pMsg->xMsgHeader.msgDstId = HIF_TASK;
+ pMsg->xMsgHeader.msgFlags = 0;
+ pMsg->xMsgHeader.msgLength = (u16) totalLen;
+ pMsg->msgData[0] = PinNum;
+
+ if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
+ pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ;
+ if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum,
+ &groupCfg) != 0)
+ return -EINVAL;
+
+ pMsg->msgData[1] = TranslatedPinNum;
+ pMsg->msgData[2] = GroupNum;
+ ElectricChar = (pGpioConfig->PullUpDown)
+ | (pGpioConfig->InputCharacteristics << 2)
+ | (pGpioConfig->OutputSlewRate << 3)
+ | (pGpioConfig->OutputDriving << 4);
+ pMsg->msgData[3] = ElectricChar;
+ pMsg->msgData[4] = pGpioConfig->Direction;
+ pMsg->msgData[5] = groupCfg;
+ } else {
+ pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ;
+ pMsg->msgData[1] = pGpioConfig->PullUpDown;
+ pMsg->msgData[2] = pGpioConfig->OutputSlewRate;
+ pMsg->msgData[3] = pGpioConfig->OutputDriving;
+ pMsg->msgData[4] = pGpioConfig->Direction;
+ pMsg->msgData[5] = 0;
}
-#endif
-#if 0 /* def SMS_USB_BUS_DRV */
- /* USB Register */
- rc = smsusb_register();
- if (rc) {
- sms_err("Error registering USB bus driver.\n");
- goto sms_bus_drv_error;
+ smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+ rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+ &coredev->gpio_configuration_done);
+
+ if (rc != 0) {
+ if (rc == -ETIME)
+ sms_err("smscore_gpio_configure timeout");
+ else
+ sms_err("smscore_gpio_configure error");
}
-#endif
+ kfree(buffer);
+
+ return rc;
+}
+
+int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
+ u8 NewLevel) {
+
+ u32 totalLen;
+ int rc;
+ void *buffer;
+
+ struct SetGpioMsg {
+ struct SmsMsgHdr_ST xMsgHeader;
+ u32 msgData[3]; /* keep it 3 ! */
+ } *pMsg;
+
+ if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER) ||
+ (PinNum > MAX_GPIO_PIN_NUMBER))
+ return -EINVAL;
+
+ totalLen = sizeof(struct SmsMsgHdr_ST) +
+ (3 * sizeof(u32)); /* keep it 3 ! */
-#if 0 /* def SMS_SPI_BUS_DRV */
- /* USB Register */
- rc = smsspi_register();
- if (rc) {
- sms_err("Error registering spi bus driver.\n");
- goto sms_bus_drv_error;
+ buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+ GFP_KERNEL | GFP_DMA);
+ if (!buffer)
+ return -ENOMEM;
+
+ pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+ pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+ pMsg->xMsgHeader.msgDstId = HIF_TASK;
+ pMsg->xMsgHeader.msgFlags = 0;
+ pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ;
+ pMsg->xMsgHeader.msgLength = (u16) totalLen;
+ pMsg->msgData[0] = PinNum;
+ pMsg->msgData[1] = NewLevel;
+
+ /* Send message to SMS */
+ smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+ rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+ &coredev->gpio_set_level_done);
+
+ if (rc != 0) {
+ if (rc == -ETIME)
+ sms_err("smscore_gpio_set_level timeout");
+ else
+ sms_err("smscore_gpio_set_level error");
}
-#endif
+ kfree(buffer);
return rc;
-#if 0
-sms_bus_drv_error:
-#endif /* 0 */
-#if 0 /* def SMS_NET_CLIENT */
- smsnet_unregister();
-smsnet_error:
-#endif
-#if 0 /* def SMS_DVB_CLIENT */
- smsdvb_unregister();
-smsdvb_error:
-#endif
-#if 0 /* def SMS_CHAR_CLIENT */
- smschar_unregister();
-smschar_error:
-#endif
- sms_debug("rc %d", rc);
+}
+
+int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+ u8 *level) {
+
+ u32 totalLen;
+ int rc;
+ void *buffer;
+
+ struct SetGpioMsg {
+ struct SmsMsgHdr_ST xMsgHeader;
+ u32 msgData[2];
+ } *pMsg;
+
+
+ if (PinNum > MAX_GPIO_PIN_NUMBER)
+ return -EINVAL;
+
+ totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32));
+
+ buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+ GFP_KERNEL | GFP_DMA);
+ if (!buffer)
+ return -ENOMEM;
+
+ pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+ pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+ pMsg->xMsgHeader.msgDstId = HIF_TASK;
+ pMsg->xMsgHeader.msgFlags = 0;
+ pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ;
+ pMsg->xMsgHeader.msgLength = (u16) totalLen;
+ pMsg->msgData[0] = PinNum;
+ pMsg->msgData[1] = 0;
+
+ /* Send message to SMS */
+ smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+ rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+ &coredev->gpio_get_level_done);
+
+ if (rc != 0) {
+ if (rc == -ETIME)
+ sms_err("smscore_gpio_get_level timeout");
+ else
+ sms_err("smscore_gpio_get_level error");
+ }
+ kfree(buffer);
+
+ /* Its a race between other gpio_get_level() and the copy of the single
+ * global 'coredev->gpio_get_res' to the function's variable 'level'
+ */
+ *level = coredev->gpio_get_res;
return rc;
}
-static void __exit smscore_module_exit(void)
+static int __init smscore_module_init(void)
{
-#if 0 /* def SMS_CHAR_CLIENT */
- /* Char interface UnRegister */
- smschar_unregister();
-#endif
-
-#if 0 /* def SMS_DVB_CLIENT */
- /* DVB UnRegister */
- smsdvb_unregister();
-#endif
+ int rc = 0;
-#if 0 /* def SMS_NET_CLIENT */
- /* NET UnRegister */
- smsnet_unregister();
-#endif
+ INIT_LIST_HEAD(&g_smscore_notifyees);
+ INIT_LIST_HEAD(&g_smscore_devices);
+ kmutex_init(&g_smscore_deviceslock);
-#if 0 /* def SMS_USB_BUS_DRV */
- /* Unregister USB */
- smsusb_unregister();
-#endif
+ INIT_LIST_HEAD(&g_smscore_registry);
+ kmutex_init(&g_smscore_registrylock);
-#if 0 /* def SMS_SPI_BUS_DRV */
- /* Unregister SPI */
- smsspi_unregister();
-#endif
+ return rc;
+}
+static void __exit smscore_module_exit(void)
+{
kmutex_lock(&g_smscore_deviceslock);
while (!list_empty(&g_smscore_notifyees)) {
struct smscore_device_notifyee_t *notifyee =
diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h
index f4aa406ef..bc4572de6 100644
--- a/linux/drivers/media/dvb/siano/smscoreapi.h
+++ b/linux/drivers/media/dvb/siano/smscoreapi.h
@@ -550,7 +550,7 @@ struct SMSHOSTLIB_I2C_RES_ST {
};
-struct smscore_gpio_config {
+struct smscore_config_gpio {
#define SMS_GPIO_DIRECTION_INPUT 0
#define SMS_GPIO_DIRECTION_OUTPUT 1
u8 direction;
@@ -576,6 +576,47 @@ struct smscore_gpio_config {
u8 outputdriving;
};
+struct smscore_gpio_config {
+#define SMS_GPIO_DIRECTION_INPUT 0
+#define SMS_GPIO_DIRECTION_OUTPUT 1
+ u8 Direction;
+
+#define SMS_GPIO_PULL_UP_DOWN_NONE 0
+#define SMS_GPIO_PULL_UP_DOWN_PULLDOWN 1
+#define SMS_GPIO_PULL_UP_DOWN_PULLUP 2
+#define SMS_GPIO_PULL_UP_DOWN_KEEPER 3
+ u8 PullUpDown;
+
+#define SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL 0
+#define SMS_GPIO_INPUT_CHARACTERISTICS_SCHMITT 1
+ u8 InputCharacteristics;
+
+#define SMS_GPIO_OUTPUT_SLEW_RATE_SLOW 1 /* 10xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_FAST 0 /* 10xx */
+
+
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS 0 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS 1 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS 2 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS 3 /* 11xx */
+ u8 OutputSlewRate;
+
+#define SMS_GPIO_OUTPUT_DRIVING_S_4mA 0 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_8mA 1 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_12mA 2 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_16mA 3 /* 10xx */
+
+#define SMS_GPIO_OUTPUT_DRIVING_1_5mA 0 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_2_8mA 1 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_4mA 2 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_7mA 3 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_10mA 4 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_11mA 5 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_14mA 6 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_16mA 7 /* 11xx */
+ u8 OutputDriving;
+};
+
extern void smscore_registry_setmode(char *devpath, int mode);
extern int smscore_registry_getmode(char *devpath);
@@ -604,7 +645,6 @@ extern int smsclient_sendrequest(struct smscore_client_t *client,
extern void smscore_onresponse(struct smscore_device_t *coredev,
struct smscore_buffer_t *cb);
-#if 1
extern int smscore_get_common_buffer_size(struct smscore_device_t *coredev);
extern int smscore_map_common_buffer(struct smscore_device_t *coredev,
struct vm_area_struct *vma);
@@ -612,17 +652,25 @@ extern int smscore_get_fw_filename(struct smscore_device_t *coredev,
int mode, char *filename);
extern int smscore_send_fw_file(struct smscore_device_t *coredev,
u8 *ufwbuf, int size);
-#endif
extern
struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev);
extern void smscore_putbuffer(struct smscore_device_t *coredev,
struct smscore_buffer_t *cb);
+/* old GPIO managment */
int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
- struct smscore_gpio_config *pinconfig);
+ struct smscore_config_gpio *pinconfig);
int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level);
+/* new GPIO managment */
+extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
+ struct smscore_gpio_config *pGpioConfig);
+extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
+ u8 NewLevel);
+extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+ u8 *level);
+
void smscore_set_board_id(struct smscore_device_t *core, int id);
int smscore_get_board_id(struct smscore_device_t *core);
diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c
index 39421ee6f..f8856d9c8 100644
--- a/linux/drivers/media/dvb/siano/smsdvb.c
+++ b/linux/drivers/media/dvb/siano/smsdvb.c
@@ -66,6 +66,54 @@ MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
/* Events that may come from DVB v3 adapter */
static void sms_board_dvb3_event(struct smsdvb_client_t *client,
enum SMS_DVB3_EVENTS event) {
+
+ struct smscore_device_t *coredev = client->coredev;
+ switch (event) {
+ case DVB3_EVENT_INIT:
+ sms_debug("DVB3_EVENT_INIT");
+ sms_board_event(coredev, BOARD_EVENT_BIND);
+ break;
+ case DVB3_EVENT_SLEEP:
+ sms_debug("DVB3_EVENT_SLEEP");
+ sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
+ break;
+ case DVB3_EVENT_HOTPLUG:
+ sms_debug("DVB3_EVENT_HOTPLUG");
+ sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
+ break;
+ case DVB3_EVENT_FE_LOCK:
+ if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
+ client->event_fe_state = DVB3_EVENT_FE_LOCK;
+ sms_debug("DVB3_EVENT_FE_LOCK");
+ sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
+ }
+ break;
+ case DVB3_EVENT_FE_UNLOCK:
+ if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
+ client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
+ sms_debug("DVB3_EVENT_FE_UNLOCK");
+ sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
+ }
+ break;
+ case DVB3_EVENT_UNC_OK:
+ if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
+ client->event_unc_state = DVB3_EVENT_UNC_OK;
+ sms_debug("DVB3_EVENT_UNC_OK");
+ sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
+ }
+ break;
+ case DVB3_EVENT_UNC_ERR:
+ if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
+ client->event_unc_state = DVB3_EVENT_UNC_ERR;
+ sms_debug("DVB3_EVENT_UNC_ERR");
+ sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
+ }
+ break;
+
+ default:
+ sms_err("Unknown dvb3 api event");
+ break;
+ }
}
static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
diff --git a/linux/drivers/media/dvb/siano/smsendian.h b/linux/drivers/media/dvb/siano/smsendian.h
index 7fbedc6a6..1624d6fd3 100644
--- a/linux/drivers/media/dvb/siano/smsendian.h
+++ b/linux/drivers/media/dvb/siano/smsendian.h
@@ -24,9 +24,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <asm/byteorder.h>
-void smsendian_handle_tx_message(void *buffer);
-void smsendian_handle_rx_message(void *buffer);
-void smsendian_handle_message_header(void *msg);
+extern void smsendian_handle_tx_message(void *buffer);
+extern void smsendian_handle_rx_message(void *buffer);
+extern void smsendian_handle_message_header(void *msg);
#endif /* __SMS_ENDIAN_H__ */
diff --git a/linux/drivers/media/dvb/siano/smssdio.c b/linux/drivers/media/dvb/siano/smssdio.c
index 4f8fa59a9..dfaa49a53 100644
--- a/linux/drivers/media/dvb/siano/smssdio.c
+++ b/linux/drivers/media/dvb/siano/smssdio.c
@@ -332,7 +332,7 @@ static struct sdio_driver smssdio_driver = {
/* Module functions */
/*******************************************************************/
-int smssdio_register(void)
+int smssdio_module_init(void)
{
int ret = 0;
@@ -344,11 +344,14 @@ int smssdio_register(void)
return ret;
}
-void smssdio_unregister(void)
+void smssdio_module_exit(void)
{
sdio_unregister_driver(&smssdio_driver);
}
+module_init(smssdio_module_init);
+module_exit(smssdio_module_exit);
+
MODULE_DESCRIPTION("Siano SMS1xxx SDIO driver");
MODULE_AUTHOR("Pierre Ossman");
MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c
index 3bbbdb197..c31a52d3a 100644
--- a/linux/drivers/media/dvb/siano/smsusb.c
+++ b/linux/drivers/media/dvb/siano/smsusb.c
@@ -489,7 +489,6 @@ static int smsusb_resume(struct usb_interface *intf)
}
struct usb_device_id smsusb_id_table[] = {
-#ifdef CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS
{ USB_DEVICE(0x187f, 0x0010),
.driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
{ USB_DEVICE(0x187f, 0x0100),
@@ -500,7 +499,6 @@ struct usb_device_id smsusb_id_table[] = {
.driver_info = SMS1XXX_BOARD_SIANO_NOVA_B },
{ USB_DEVICE(0x187f, 0x0300),
.driver_info = SMS1XXX_BOARD_SIANO_VEGA },
-#endif
{ USB_DEVICE(0x2040, 0x1700),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT },
{ USB_DEVICE(0x2040, 0x1800),
@@ -531,8 +529,13 @@ struct usb_device_id smsusb_id_table[] = {
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0x5590),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
- { } /* Terminating entry */
-};
+ { USB_DEVICE(0x187f, 0x0202),
+ .driver_info = SMS1XXX_BOARD_SIANO_NICE },
+ { USB_DEVICE(0x187f, 0x0301),
+ .driver_info = SMS1XXX_BOARD_SIANO_VENICE },
+ { } /* Terminating entry */
+ };
+
MODULE_DEVICE_TABLE(usb, smsusb_id_table);
static struct usb_driver smsusb_driver = {
diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c
index 8d2075186..67d06eb6c 100644
--- a/linux/drivers/media/video/bt8xx/bttv-driver.c
+++ b/linux/drivers/media/video/bt8xx/bttv-driver.c
@@ -4665,7 +4665,7 @@ static int __init bttv_init_module(void)
#endif
if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
gbuffers = 2;
- if (gbufsize < 0 || gbufsize > BTTV_MAX_FBUF)
+ if (gbufsize > BTTV_MAX_FBUF)
gbufsize = BTTV_MAX_FBUF;
gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
if (bttv_verbose)
diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c
index 0b3d840cc..536dedb23 100644
--- a/linux/drivers/media/video/cx18/cx18-av-core.c
+++ b/linux/drivers/media/video/cx18/cx18-av-core.c
@@ -447,6 +447,7 @@ void cx18_av_std_setup(struct cx18 *cx)
if (pll_post) {
int fsc, pll;
+ u64 tmp;
pll = (28636360L * ((((u64)pll_int) << 25) + pll_frac)) >> 25;
pll /= pll_post;
@@ -459,7 +460,9 @@ void cx18_av_std_setup(struct cx18 *cx)
"= %d.%03d\n", src_decimation / 256,
((src_decimation % 256) * 1000) / 256);
- fsc = ((((u64)sc) * 28636360)/src_decimation) >> 13L;
+ tmp = 28636360 * (u64) sc;
+ do_div(tmp, src_decimation);
+ fsc = tmp >> 13;
CX18_DEBUG_INFO_DEV(sd,
"Chroma sub-carrier initial freq = %d.%06d "
"MHz\n", fsc / 1000000, fsc % 1000000);
diff --git a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c
index 6a9464079..bbbb3f50e 100644
--- a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c
+++ b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c
@@ -1052,22 +1052,13 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev,
/* Set resolution of the video */
int cx231xx_resolution_set(struct cx231xx *dev)
{
- int width, height;
- u32 hscale, vscale;
- int status = 0;
-
- width = dev->width;
- height = dev->height;
-
- get_scale(dev, width, height, &hscale, &vscale);
-
/* set horzontal scale */
- status = vid_blk_write_word(dev, HSCALE_CTRL, hscale);
+ int status = vid_blk_write_word(dev, HSCALE_CTRL, dev->hscale);
+ if (status)
+ return status;
/* set vertical scale */
- status = vid_blk_write_word(dev, VSCALE_CTRL, vscale);
-
- return status;
+ return vid_blk_write_word(dev, VSCALE_CTRL, dev->vscale);
}
/******************************************************************************
diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c
index 638a8d3e4..e00edd0aa 100644
--- a/linux/drivers/media/video/cx231xx/cx231xx-video.c
+++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c
@@ -893,9 +893,9 @@ static int check_dev(struct cx231xx *dev)
return 0;
}
-void get_scale(struct cx231xx *dev,
- unsigned int width, unsigned int height,
- unsigned int *hscale, unsigned int *vscale)
+static void get_scale(struct cx231xx *dev,
+ unsigned int width, unsigned int height,
+ unsigned int *hscale, unsigned int *vscale)
{
unsigned int maxw = norm_maxw(dev);
unsigned int maxh = norm_maxh(dev);
@@ -907,10 +907,6 @@ void get_scale(struct cx231xx *dev,
*vscale = (((unsigned long)maxh) << 12) / height - 4096L;
if (*vscale >= 0x4000)
*vscale = 0x3fff;
-
- dev->hscale = *hscale;
- dev->vscale = *vscale;
-
}
/* ------------------------------------------------------------------
@@ -955,8 +951,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
{
struct cx231xx_fh *fh = priv;
struct cx231xx *dev = fh->dev;
- int width = f->fmt.pix.width;
- int height = f->fmt.pix.height;
+ unsigned int width = f->fmt.pix.width;
+ unsigned int height = f->fmt.pix.height;
unsigned int maxw = norm_maxw(dev);
unsigned int maxh = norm_maxh(dev);
unsigned int hscale, vscale;
@@ -971,17 +967,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
/* width must even because of the YUYV format
height must be even because of interlacing */
- height &= 0xfffe;
- width &= 0xfffe;
-
- if (unlikely(height < 32))
- height = 32;
- if (unlikely(height > maxh))
- height = maxh;
- if (unlikely(width < 48))
- width = 48;
- if (unlikely(width > maxw))
- width = maxw;
+ v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0);
get_scale(dev, width, height, &hscale, &vscale);
diff --git a/linux/drivers/media/video/cx231xx/cx231xx.h b/linux/drivers/media/video/cx231xx/cx231xx.h
index c436f2b0d..051ca21c1 100644
--- a/linux/drivers/media/video/cx231xx/cx231xx.h
+++ b/linux/drivers/media/video/cx231xx/cx231xx.h
@@ -731,9 +731,6 @@ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input);
int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input);
int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev);
int cx231xx_set_audio_input(struct cx231xx *dev, u8 input);
-void get_scale(struct cx231xx *dev,
- unsigned int width, unsigned int height,
- unsigned int *hscale, unsigned int *vscale);
/* Provided by cx231xx-video.c */
int cx231xx_register_extension(struct cx231xx_ops *dev);
diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c
index 93176fe4b..35b2abd6a 100644
--- a/linux/drivers/media/video/cx23885/cx23885-cards.c
+++ b/linux/drivers/media/video/cx23885/cx23885-cards.c
@@ -198,6 +198,10 @@ struct cx23885_board cx23885_boards[] = {
.name = "Hauppauge WinTV-HVR1210",
.portc = CX23885_MPEG_DVB,
},
+ [CX23885_BOARD_MYGICA_X8506] = {
+ .name = "Mygica X8506 DMB-TH",
+ .portb = CX23885_MPEG_DVB,
+ },
};
const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
@@ -317,6 +321,10 @@ struct cx23885_subid cx23885_subids[] = {
.subvendor = 0x0070,
.subdevice = 0x2295,
.card = CX23885_BOARD_HAUPPAUGE_HVR1210,
+ }, {
+ .subvendor = 0x14f1,
+ .subdevice = 0x8651,
+ .card = CX23885_BOARD_MYGICA_X8506,
},
};
const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -707,6 +715,15 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
mdelay(20);
cx23885_gpio_set(dev, GPIO_9);
break;
+ case CX23885_BOARD_MYGICA_X8506:
+ /* GPIO-1 reset XC5000 */
+ /* GPIO-2 reset LGS8GL5 */
+ cx_set(GP0_IO, 0x00060000);
+ cx_clear(GP0_IO, 0x00000006);
+ mdelay(100);
+ cx_set(GP0_IO, 0x00060006);
+ mdelay(100);
+ break;
}
}
@@ -810,6 +827,11 @@ void cx23885_card_setup(struct cx23885_dev *dev)
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
break;
+ case CX23885_BOARD_MYGICA_X8506:
+ ts1->gen_ctrl_val = 0x5; /* Parallel */
+ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+ break;
case CX23885_BOARD_HAUPPAUGE_HVR1250:
case CX23885_BOARD_HAUPPAUGE_HVR1500:
case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c
index 4efc7dee1..9c3259b22 100644
--- a/linux/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c
@@ -50,6 +50,7 @@
#include "lnbh24.h"
#include "cx24116.h"
#include "cimax2.h"
+#include "lgs8gxx.h"
#include "netup-eeprom.h"
#include "netup-init.h"
#include "lgdt3305.h"
@@ -421,10 +422,29 @@ static struct cx24116_config dvbworld_cx24116_config = {
.demod_address = 0x05,
};
+static struct lgs8gxx_config mygica_x8506_lgs8gl5_config = {
+ .prod = LGS8GXX_PROD_LGS8GL5,
+ .demod_address = 0x19,
+ .serial_ts = 0,
+ .ts_clk_pol = 1,
+ .ts_clk_gated = 1,
+ .if_clk_freq = 30400, /* 30.4 MHz */
+ .if_freq = 5380, /* 5.38 MHz */
+ .if_neg_center = 1,
+ .ext_adc = 0,
+ .adc_signed = 0,
+ .if_neg_edge = 0,
+};
+
+static struct xc5000_config mygica_x8506_xc5000_config = {
+ .i2c_address = 0x61,
+ .if_khz = 5380,
+};
+
static int dvb_register(struct cx23885_tsport *port)
{
struct cx23885_dev *dev = port->dev;
- struct cx23885_i2c *i2c_bus = NULL;
+ struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL;
struct videobuf_dvb_frontend *fe0;
int ret;
@@ -746,6 +766,19 @@ static int dvb_register(struct cx23885_tsport *port)
break;
}
break;
+ case CX23885_BOARD_MYGICA_X8506:
+ i2c_bus = &dev->i2c_bus[0];
+ i2c_bus2 = &dev->i2c_bus[1];
+ fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
+ &mygica_x8506_lgs8gl5_config,
+ &i2c_bus->i2c_adap);
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(xc5000_attach,
+ fe0->dvb.frontend,
+ &i2c_bus2->i2c_adap,
+ &mygica_x8506_xc5000_config);
+ }
+ break;
default:
printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
" isn't supported yet\n",
diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c
index 2855a49b5..378943605 100644
--- a/linux/drivers/media/video/cx23885/cx23885-video.c
+++ b/linux/drivers/media/video/cx23885/cx23885-video.c
@@ -1035,15 +1035,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
}
f->fmt.pix.field = field;
- if (f->fmt.pix.height < 32)
- f->fmt.pix.height = 32;
- if (f->fmt.pix.height > maxh)
- f->fmt.pix.height = maxh;
- if (f->fmt.pix.width < 48)
- f->fmt.pix.width = 48;
- if (f->fmt.pix.width > maxw)
- f->fmt.pix.width = maxw;
- f->fmt.pix.width &= ~0x03;
+ v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
+ &f->fmt.pix.height, 32, maxh, 0, 0);
f->fmt.pix.bytesperline =
(f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h
index 8dba2fdd6..2022ed7de 100644
--- a/linux/drivers/media/video/cx23885/cx23885.h
+++ b/linux/drivers/media/video/cx23885/cx23885.h
@@ -76,6 +76,7 @@
#define CX23885_BOARD_HAUPPAUGE_HVR1275 19
#define CX23885_BOARD_HAUPPAUGE_HVR1255 20
#define CX23885_BOARD_HAUPPAUGE_HVR1210 21
+#define CX23885_BOARD_MYGICA_X8506 22
#define GPIO_0 0x00000001
#define GPIO_1 0x00000002
diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c
index 546793c02..825b1f25d 100644
--- a/linux/drivers/media/video/cx88/cx88-cards.c
+++ b/linux/drivers/media/video/cx88/cx88-cards.c
@@ -2009,6 +2009,47 @@ static const struct cx88_board cx88_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
+ [CX88_BOARD_WINFAST_DTV1800H] = {
+ .name = "Leadtek WinFast DTV1800 Hybrid",
+ .tuner_type = TUNER_XC2028,
+ .radio_type = TUNER_XC2028,
+ .tuner_addr = 0x61,
+ .radio_addr = 0x61,
+ /*
+ * GPIO setting
+ *
+ * 2: mute (0=off,1=on)
+ * 12: tuner reset pin
+ * 13: audio source (0=tuner audio,1=line in)
+ * 14: FM (0=on,1=off ???)
+ */
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x6040, /* pin 13 = 0, pin 14 = 1 */
+ .gpio2 = 0x0000,
+ }, {
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */
+ .gpio2 = 0x0000,
+ }, {
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */
+ .gpio2 = 0x0000,
+ } },
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x6000, /* pin 13 = 0, pin 14 = 0 */
+ .gpio2 = 0x0000,
+ },
+ .mpeg = CX88_MPEG_DVB,
+ },
};
/* ------------------------------------------------------------------ */
@@ -2426,6 +2467,10 @@ static const struct cx88_subid cx88_subids[] = {
.subvendor = 0x0070,
.subdevice = 0x9290,
.card = CX88_BOARD_HAUPPAUGE_IRONLY,
+ }, {
+ .subvendor = 0x107d,
+ .subdevice = 0x6654,
+ .card = CX88_BOARD_WINFAST_DTV1800H,
},
};
@@ -2624,6 +2669,23 @@ static int cx88_xc3028_geniatech_tuner_callback(struct cx88_core *core,
return -EINVAL;
}
+static int cx88_xc3028_winfast1800h_callback(struct cx88_core *core,
+ int command, int arg)
+{
+ switch (command) {
+ case XC2028_TUNER_RESET:
+ /* GPIO 12 (xc3028 tuner reset) */
+ cx_set(MO_GP1_IO, 0x1010);
+ mdelay(50);
+ cx_clear(MO_GP1_IO, 0x10);
+ mdelay(50);
+ cx_set(MO_GP1_IO, 0x10);
+ mdelay(50);
+ return 0;
+ }
+ return -EINVAL;
+}
+
/* ------------------------------------------------------------------- */
/* some Divco specific stuff */
static int cx88_pv_8000gt_callback(struct cx88_core *core,
@@ -2696,6 +2758,8 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core,
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
return cx88_dvico_xc2028_callback(core, command, arg);
+ case CX88_BOARD_WINFAST_DTV1800H:
+ return cx88_xc3028_winfast1800h_callback(core, command, arg);
}
switch (command) {
@@ -2882,6 +2946,16 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
udelay(1000);
break;
+
+ case CX88_BOARD_WINFAST_DTV1800H:
+ /* GPIO 12 (xc3028 tuner reset) */
+ cx_set(MO_GP1_IO, 0x1010);
+ mdelay(50);
+ cx_clear(MO_GP1_IO, 0x10);
+ mdelay(50);
+ cx_set(MO_GP1_IO, 0x10);
+ mdelay(50);
+ break;
}
}
@@ -2902,6 +2976,7 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl)
core->i2c_algo.udelay = 16;
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+ case CX88_BOARD_WINFAST_DTV1800H:
ctl->demod = XC3028_FE_ZARLINK456;
break;
case CX88_BOARD_KWORLD_ATSC_120:
diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c
index f32cece95..36f35f0b5 100644
--- a/linux/drivers/media/video/cx88/cx88-dvb.c
+++ b/linux/drivers/media/video/cx88/cx88-dvb.c
@@ -1021,6 +1021,7 @@ static int dvb_register(struct cx8802_dev *dev)
}
break;
case CX88_BOARD_PINNACLE_HYBRID_PCTV:
+ case CX88_BOARD_WINFAST_DTV1800H:
fe0->dvb.frontend = dvb_attach(zl10353_attach,
&cx88_pinnacle_hybrid_pctv,
&core->i2c_adap);
diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c
index dad809335..7c5e94916 100644
--- a/linux/drivers/media/video/cx88/cx88-input.c
+++ b/linux/drivers/media/video/cx88/cx88-input.c
@@ -92,6 +92,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
gpio=(gpio & 0x7fd) + (auxgpio & 0xef);
break;
case CX88_BOARD_WINFAST_DTV1000:
+ case CX88_BOARD_WINFAST_DTV1800H:
case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900);
auxgpio = gpio;
@@ -237,6 +238,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
ir->sampling = 1;
break;
case CX88_BOARD_WINFAST_DTV2000H:
+ case CX88_BOARD_WINFAST_DTV1800H:
ir_codes = ir_codes_winfast;
ir->gpio_addr = MO_GP0_IO;
ir->mask_keycode = 0x8f8;
diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c
index 2dfa4c9c3..70b086fb7 100644
--- a/linux/drivers/media/video/cx88/cx88-video.c
+++ b/linux/drivers/media/video/cx88/cx88-video.c
@@ -1339,15 +1339,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
}
f->fmt.pix.field = field;
- if (f->fmt.pix.height < 32)
- f->fmt.pix.height = 32;
- if (f->fmt.pix.height > maxh)
- f->fmt.pix.height = maxh;
- if (f->fmt.pix.width < 48)
- f->fmt.pix.width = 48;
- if (f->fmt.pix.width > maxw)
- f->fmt.pix.width = maxw;
- f->fmt.pix.width &= ~0x03;
+ v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
+ &f->fmt.pix.height, 32, maxh, 0, 0);
f->fmt.pix.bytesperline =
(f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h
index 0c00c34bc..59fc01a53 100644
--- a/linux/drivers/media/video/cx88/cx88.h
+++ b/linux/drivers/media/video/cx88/cx88.h
@@ -237,6 +237,7 @@ extern struct sram_channel cx88_sram_channels[];
#define CX88_BOARD_PROF_6200 78
#define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79
#define CX88_BOARD_HAUPPAUGE_IRONLY 80
+#define CX88_BOARD_WINFAST_DTV1800H 81
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c
index 089764d42..66aace7cf 100644
--- a/linux/drivers/media/video/em28xx/em28xx-audio.c
+++ b/linux/drivers/media/video/em28xx/em28xx-audio.c
@@ -385,6 +385,11 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
mutex_lock(&dev->lock);
dev->adev.users--;
em28xx_audio_analog_set(dev);
+ if (substream->runtime->dma_area) {
+ dprintk("freeing\n");
+ vfree(substream->runtime->dma_area);
+ substream->runtime->dma_area = NULL;
+ }
mutex_unlock(&dev->lock);
return 0;
diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c
index 1614e5fc4..63d21698c 100644
--- a/linux/drivers/media/video/em28xx/em28xx-video.c
+++ b/linux/drivers/media/video/em28xx/em28xx-video.c
@@ -691,8 +691,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
{
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
- int width = f->fmt.pix.width;
- int height = f->fmt.pix.height;
+ unsigned int width = f->fmt.pix.width;
+ unsigned int height = f->fmt.pix.height;
unsigned int maxw = norm_maxw(dev);
unsigned int maxh = norm_maxh(dev);
unsigned int hscale, vscale;
@@ -705,34 +705,20 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
return -EINVAL;
}
- /* width must even because of the YUYV format
- height must be even because of interlacing */
- height &= 0xfffe;
- width &= 0xfffe;
-
- if (unlikely(height < 32))
- height = 32;
- if (unlikely(height > maxh))
- height = maxh;
- if (unlikely(width < 48))
- width = 48;
- if (unlikely(width > maxw))
- width = maxw;
-
if (dev->board.is_em2800) {
/* the em2800 can only scale down to 50% */
- if (height % (maxh / 2))
- height = maxh;
- if (width % (maxw / 2))
- width = maxw;
- /* according to empiatech support */
- /* the MaxPacketSize is to small to support */
- /* framesizes larger than 640x480 @ 30 fps */
- /* or 640x576 @ 25 fps. As this would cut */
- /* of a part of the image we prefer */
- /* 360x576 or 360x480 for now */
+ height = height > (3 * maxh / 4) ? maxh : maxh / 2;
+ width = width > (3 * maxw / 4) ? maxw : maxw / 2;
+ /* According to empiatech support the MaxPacketSize is too small
+ * to support framesizes larger than 640x480 @ 30 fps or 640x576
+ * @ 25 fps. As this would cut of a part of the image we prefer
+ * 360x576 or 360x480 for now */
if (width == maxw && height == maxh)
width /= 2;
+ } else {
+ /* width must even because of the YUYV format
+ height must be even because of interlacing */
+ v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0);
}
get_scale(dev, width, height, &hscale, &vscale);
diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c
index 8d61ad30a..e609d68c4 100644
--- a/linux/drivers/media/video/mt9m001.c
+++ b/linux/drivers/media/video/mt9m001.c
@@ -280,15 +280,9 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd,
{
struct v4l2_pix_format *pix = &f->fmt.pix;
- if (pix->height < 32 + icd->y_skip_top)
- pix->height = 32 + icd->y_skip_top;
- if (pix->height > 1024 + icd->y_skip_top)
- pix->height = 1024 + icd->y_skip_top;
- if (pix->width < 48)
- pix->width = 48;
- if (pix->width > 1280)
- pix->width = 1280;
- pix->width &= ~0x01; /* has to be even, unsure why was ~3 */
+ v4l_bound_align_image(&pix->width, 48, 1280, 1,
+ &pix->height, 32 + icd->y_skip_top,
+ 1024 + icd->y_skip_top, 0, 0);
return 0;
}
diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c
index 381dd0fbe..a57051522 100644
--- a/linux/drivers/media/video/mt9t031.c
+++ b/linux/drivers/media/video/mt9t031.c
@@ -385,17 +385,9 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd,
{
struct v4l2_pix_format *pix = &f->fmt.pix;
- if (pix->height < MT9T031_MIN_HEIGHT)
- pix->height = MT9T031_MIN_HEIGHT;
- if (pix->height > MT9T031_MAX_HEIGHT)
- pix->height = MT9T031_MAX_HEIGHT;
- if (pix->width < MT9T031_MIN_WIDTH)
- pix->width = MT9T031_MIN_WIDTH;
- if (pix->width > MT9T031_MAX_WIDTH)
- pix->width = MT9T031_MAX_WIDTH;
-
- pix->width &= ~0x01; /* has to be even */
- pix->height &= ~0x01; /* has to be even */
+ v4l_bound_align_image(
+ &pix->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1,
+ &pix->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0);
return 0;
}
diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c
index 016bcdfcf..4841e6eea 100644
--- a/linux/drivers/media/video/mt9v022.c
+++ b/linux/drivers/media/video/mt9v022.c
@@ -364,15 +364,9 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd,
{
struct v4l2_pix_format *pix = &f->fmt.pix;
- if (pix->height < 32 + icd->y_skip_top)
- pix->height = 32 + icd->y_skip_top;
- if (pix->height > 480 + icd->y_skip_top)
- pix->height = 480 + icd->y_skip_top;
- if (pix->width < 48)
- pix->width = 48;
- if (pix->width > 752)
- pix->width = 752;
- pix->width &= ~0x03; /* ? */
+ v4l_bound_align_image(&pix->width, 48, 752, 2 /* ? */,
+ &pix->height, 32 + icd->y_skip_top,
+ 480 + icd->y_skip_top, 0, 0);
return 0;
}
diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c
index 35642c430..2c122ec90 100644
--- a/linux/drivers/media/video/pxa_camera.c
+++ b/linux/drivers/media/video/pxa_camera.c
@@ -175,13 +175,6 @@
CICR0_EOFM | CICR0_FOM)
/*
- * YUV422P picture size should be a multiple of 16, so the heuristic aligns
- * height, width on 4 byte boundaries to reach the 16 multiple for the size.
- */
-#define YUV422P_X_Y_ALIGN 4
-#define YUV422P_SIZE_ALIGN YUV422P_X_Y_ALIGN * YUV422P_X_Y_ALIGN
-
-/*
* Structures
*/
enum pxa_camera_active_dma {
@@ -1410,28 +1403,13 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd,
return -EINVAL;
}
- /* limit to pxa hardware capabilities */
- if (pix->height < 32)
- pix->height = 32;
- if (pix->height > 2048)
- pix->height = 2048;
- if (pix->width < 48)
- pix->width = 48;
- if (pix->width > 2048)
- pix->width = 2048;
- pix->width &= ~0x01;
-
- /*
- * YUV422P planar format requires images size to be a 16 bytes
- * multiple. If not, zeros will be inserted between Y and U planes, and
- * U and V planes, and YUV422P standard would be violated.
- */
- if (xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P) {
- if (!IS_ALIGNED(pix->width * pix->height, YUV422P_SIZE_ALIGN))
- pix->height = ALIGN(pix->height, YUV422P_X_Y_ALIGN);
- if (!IS_ALIGNED(pix->width * pix->height, YUV422P_SIZE_ALIGN))
- pix->width = ALIGN(pix->width, YUV422P_X_Y_ALIGN);
- }
+ /* Limit to pxa hardware capabilities. YUV422P planar format requires
+ * images size to be a multiple of 16 bytes. If not, zeros will be
+ * inserted between Y and U planes, and U and V planes, which violates
+ * the YUV422P standard. */
+ v4l2_bound_align_image(&pix->width, 48, 2048, 1,
+ &pix->height, 32, 2048, 0,
+ xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0);
pix->bytesperline = pix->width *
DIV_ROUND_UP(xlate->host_fmt->depth, 8);
diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c
index 26f1727e6..518de9b2c 100644
--- a/linux/drivers/media/video/saa7134/saa7134-video.c
+++ b/linux/drivers/media/video/saa7134/saa7134-video.c
@@ -1448,7 +1448,7 @@ video_poll(struct file *file, struct poll_table_struct *wait)
}
if (!buf)
- rc = POLLERR;
+ goto err;
poll_wait(file, &buf->done, wait);
if (buf->state == VIDEOBUF_DONE ||
@@ -1646,15 +1646,8 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
}
f->fmt.pix.field = field;
- if (f->fmt.pix.width < 48)
- f->fmt.pix.width = 48;
- if (f->fmt.pix.height < 32)
- f->fmt.pix.height = 32;
- if (f->fmt.pix.width > maxw)
- f->fmt.pix.width = maxw;
- if (f->fmt.pix.height > maxh)
- f->fmt.pix.height = maxh;
- f->fmt.pix.width &= ~0x03;
+ v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
+ &f->fmt.pix.height, 32, maxh, 0, 0);
f->fmt.pix.bytesperline =
(f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c
index bf0b176f9..7ea2a0edf 100644
--- a/linux/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c
@@ -690,16 +690,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
/* FIXME: calculate using depth and bus width */
- if (f->fmt.pix.height < 4)
- f->fmt.pix.height = 4;
- if (f->fmt.pix.height > 1920)
- f->fmt.pix.height = 1920;
- if (f->fmt.pix.width < 2)
- f->fmt.pix.width = 2;
- if (f->fmt.pix.width > 2560)
- f->fmt.pix.width = 2560;
- f->fmt.pix.width &= ~0x01;
- f->fmt.pix.height &= ~0x03;
+ v4l_bound_align_image(&f->fmt.pix.width, 2, 2560, 1,
+ &f->fmt.pix.height, 4, 1920, 2, 0);
f->fmt.pix.bytesperline = f->fmt.pix.width *
DIV_ROUND_UP(xlate->host_fmt->depth, 8);
diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c
index 8f2db1250..d81bae197 100644
--- a/linux/drivers/media/video/v4l2-common.c
+++ b/linux/drivers/media/video/v4l2-common.c
@@ -997,4 +997,75 @@ const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type)
}
EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs);
+/* Clamp x to be between min and max, aligned to a multiple of 2^align. min
+ * and max don't have to be aligned, but there must be at least one valid
+ * value. E.g., min=17,max=31,align=4 is not allowed as there are no multiples
+ * of 16 between 17 and 31. */
+static unsigned int clamp_align(unsigned int x, unsigned int min,
+ unsigned int max, unsigned int align)
+{
+ /* Bits that must be zero to be aligned */
+ unsigned int mask = ~((1 << align) - 1);
+
+ /* Round to nearest aligned value */
+ if (align)
+ x = (x + (1 << (align - 1))) & mask;
+
+ /* Clamp to aligned value of min and max */
+ if (x < min)
+ x = (min + ~mask) & mask;
+ else if (x > max)
+ x = max & mask;
+
+ return x;
+}
+
+/* Bound an image to have a width between wmin and wmax, and height between
+ * hmin and hmax, inclusive. Additionally, the width will be a multiple of
+ * 2^walign, the height will be a multiple of 2^halign, and the overall size
+ * (width*height) will be a multiple of 2^salign. The image may be shrunk
+ * or enlarged to fit the alignment constraints.
+ *
+ * The width or height maximum must not be smaller than the corresponding
+ * minimum. The alignments must not be so high there are no possible image
+ * sizes within the allowed bounds. wmin and hmin must be at least 1
+ * (don't use 0). If you don't care about a certain alignment, specify 0,
+ * as 2^0 is 1 and one byte alignment is equivalent to no alignment. If
+ * you only want to adjust downward, specify a maximum that's the same as
+ * the initial value.
+ */
+void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
+ unsigned int walign,
+ u32 *h, unsigned int hmin, unsigned int hmax,
+ unsigned int halign, unsigned int salign)
+{
+ *w = clamp_align(*w, wmin, wmax, walign);
+ *h = clamp_align(*h, hmin, hmax, halign);
+
+ /* Usually we don't need to align the size and are done now. */
+ if (!salign)
+ return;
+
+ /* How much alignment do we have? */
+ walign = __ffs(*w);
+ halign = __ffs(*h);
+ /* Enough to satisfy the image alignment? */
+ if (walign + halign < salign) {
+ /* Max walign where there is still a valid width */
+ unsigned int wmaxa = __fls(wmax ^ (wmin - 1));
+
+ /* up the smaller alignment until we have enough */
+ do {
+ if (walign <= halign && walign < wmaxa) {
+ *w = clamp_align(*w, wmin, wmax, walign + 1);
+ walign = __ffs(*w);
+ } else {
+ *h = clamp_align(*h, hmin, hmax, halign + 1);
+ halign = __ffs(*h);
+ }
+ } while (halign + walign < salign);
+ }
+}
+EXPORT_SYMBOL_GPL(v4l_bound_align_image);
+
#endif
diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c
index e3bc2b0a3..fe39b7326 100644
--- a/linux/drivers/media/video/vivi.c
+++ b/linux/drivers/media/video/vivi.c
@@ -886,15 +886,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
maxh = norm_maxh();
f->fmt.pix.field = field;
- if (f->fmt.pix.height < 32)
- f->fmt.pix.height = 32;
- if (f->fmt.pix.height > maxh)
- f->fmt.pix.height = maxh;
- if (f->fmt.pix.width < 48)
- f->fmt.pix.width = 48;
- if (f->fmt.pix.width > maxw)
- f->fmt.pix.width = maxw;
- f->fmt.pix.width &= ~0x03;
+ v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
+ &f->fmt.pix.height, 32, maxh, 0, 0);
f->fmt.pix.bytesperline =
(f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c
index d51566ddc..86738d186 100644
--- a/linux/drivers/media/video/w9968cf.c
+++ b/linux/drivers/media/video/w9968cf.c
@@ -464,7 +464,7 @@ static int w9968cf_set_picture(struct w9968cf_device*, struct video_picture);
static int w9968cf_set_window(struct w9968cf_device*, struct video_window);
static int w9968cf_postprocess_frame(struct w9968cf_device*,
struct w9968cf_frame_t*);
-static int w9968cf_adjust_window_size(struct w9968cf_device*, u16* w, u16* h);
+static int w9968cf_adjust_window_size(struct w9968cf_device*, u32 *w, u32 *h);
static void w9968cf_init_framelist(struct w9968cf_device*);
static void w9968cf_push_frame(struct w9968cf_device*, u8 f_num);
static void w9968cf_pop_frame(struct w9968cf_device*,struct w9968cf_frame_t**);
@@ -1777,8 +1777,7 @@ w9968cf_set_window(struct w9968cf_device* cam, struct video_window win)
#define UNSC(x) ((x) >> 10)
/* Make sure we are using a supported resolution */
- if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width,
- (u16*)&win.height)))
+ if ((err = w9968cf_adjust_window_size(cam, &win.width, &win.height)))
goto error;
/* Scaling factors */
@@ -1928,12 +1927,9 @@ error:
Return 0 on success, -1 otherwise.
--------------------------------------------------------------------------*/
static int
-w9968cf_adjust_window_size(struct w9968cf_device* cam, u16* width, u16* height)
+w9968cf_adjust_window_size(struct w9968cf_device *cam, u32 *width, u32 *height)
{
- u16 maxw, maxh;
-
- if ((*width < cam->minwidth) || (*height < cam->minheight))
- return -ERANGE;
+ unsigned int maxw, maxh, align;
maxw = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) &&
w9968cf_vpp ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth)
@@ -1941,16 +1937,10 @@ w9968cf_adjust_window_size(struct w9968cf_device* cam, u16* width, u16* height)
maxh = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) &&
w9968cf_vpp ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight)
: cam->maxheight;
+ align = (cam->vpp_flag & VPP_DECOMPRESSION) ? 4 : 0;
- if (*width > maxw)
- *width = maxw;
- if (*height > maxh)
- *height = maxh;
-
- if (cam->vpp_flag & VPP_DECOMPRESSION) {
- *width &= ~15L; /* multiple of 16 */
- *height &= ~15L;
- }
+ v4l_bound_align_image(width, cam->minwidth, maxw, align,
+ height, cam->minheight, maxh, align, 0);
PDBGG("Window size adjusted w=%u, h=%u ", *width, *height)
@@ -3057,8 +3047,8 @@ static long w9968cf_v4l_ioctl(struct file *filp,
if (win.clipcount != 0 || win.flags != 0)
return -EINVAL;
- if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width,
- (u16*)&win.height))) {
+ if ((err = w9968cf_adjust_window_size(cam, &win.width,
+ &win.height))) {
DBG(4, "Resolution not supported (%ux%u). "
"VIDIOCSWIN failed", win.width, win.height)
return err;
@@ -3130,6 +3120,7 @@ static long w9968cf_v4l_ioctl(struct file *filp,
{
struct video_mmap mmap;
struct w9968cf_frame_t* fr;
+ u32 w, h;
int err = 0;
if (copy_from_user(&mmap, arg, sizeof(mmap)))
@@ -3178,8 +3169,10 @@ static long w9968cf_v4l_ioctl(struct file *filp,
}
}
- if ((err = w9968cf_adjust_window_size(cam, (u16*)&mmap.width,
- (u16*)&mmap.height))) {
+ w = mmap.width; h = mmap.height;
+ err = w9968cf_adjust_window_size(cam, &w, &h);
+ mmap.width = w; mmap.height = h;
+ if (err) {
DBG(4, "Resolution not supported (%dx%d). "
"VIDIOCMCAPTURE failed",
mmap.width, mmap.height)
diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c
index 793395074..8c17d47b3 100644
--- a/linux/drivers/media/video/zoran/zoran_driver.c
+++ b/linux/drivers/media/video/zoran/zoran_driver.c
@@ -2096,16 +2096,10 @@ static int zoran_try_fmt_vid_cap(struct file *file, void *__fh,
return -EINVAL;
}
- bpp = (zoran_formats[i].depth + 7) / 8;
- fmt->fmt.pix.width &= ~((bpp == 2) ? 1 : 3);
- if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
- fmt->fmt.pix.width = BUZ_MAX_WIDTH;
- if (fmt->fmt.pix.width < BUZ_MIN_WIDTH)
- fmt->fmt.pix.width = BUZ_MIN_WIDTH;
- if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
- fmt->fmt.pix.height = BUZ_MAX_HEIGHT;
- if (fmt->fmt.pix.height < BUZ_MIN_HEIGHT)
- fmt->fmt.pix.height = BUZ_MIN_HEIGHT;
+ bpp = DIV_ROUND_UP(zoran_formats[i].depth, 8);
+ v4l_bound_align_image(
+ &fmt->fmt.pix.width, BUZ_MIN_WIDTH, BUZ_MAX_WIDTH, bpp == 2 ? 1 : 2,
+ &fmt->fmt.pix.height, BUZ_MIN_HEIGHT, BUZ_MAX_HEIGHT, 0, 0);
mutex_unlock(&zr->resource_lock);
return 0;
diff --git a/linux/include/media/v4l2-common.h b/linux/include/media/v4l2-common.h
index 2e1e3a293..54728d4c0 100644
--- a/linux/include/media/v4l2-common.h
+++ b/linux/include/media/v4l2-common.h
@@ -198,4 +198,14 @@ struct v4l2_routing {
u32 output;
};
+/* ------------------------------------------------------------------------- */
+
+/* Miscellaneous helper functions */
+
+void v4l_bound_align_image(unsigned int *w, unsigned int wmin,
+ unsigned int wmax, unsigned int walign,
+ unsigned int *h, unsigned int hmin,
+ unsigned int hmax, unsigned int halign,
+ unsigned int salign);
+
#endif /* V4L2_COMMON_H_ */