18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Support for a cx23417 mpeg encoder via cx231xx host port. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * (c) 2004 Jelle Foks <jelle@foks.us> 78c2ecf20Sopenharmony_ci * (c) 2004 Gerd Knorr <kraxel@bytesex.org> 88c2ecf20Sopenharmony_ci * (c) 2008 Steven Toth <stoth@linuxtv.org> 98c2ecf20Sopenharmony_ci * - CX23885/7/8 support 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/), 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include "cx231xx.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/module.h> 178c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 188c2ecf20Sopenharmony_ci#include <linux/init.h> 198c2ecf20Sopenharmony_ci#include <linux/fs.h> 208c2ecf20Sopenharmony_ci#include <linux/delay.h> 218c2ecf20Sopenharmony_ci#include <linux/device.h> 228c2ecf20Sopenharmony_ci#include <linux/firmware.h> 238c2ecf20Sopenharmony_ci#include <linux/slab.h> 248c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 258c2ecf20Sopenharmony_ci#include <media/v4l2-common.h> 268c2ecf20Sopenharmony_ci#include <media/v4l2-ioctl.h> 278c2ecf20Sopenharmony_ci#include <media/v4l2-event.h> 288c2ecf20Sopenharmony_ci#include <media/drv-intf/cx2341x.h> 298c2ecf20Sopenharmony_ci#include <media/tuner.h> 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define CX231xx_FIRM_IMAGE_SIZE 376836 328c2ecf20Sopenharmony_ci#define CX231xx_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw" 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* for polaris ITVC */ 358c2ecf20Sopenharmony_ci#define ITVC_WRITE_DIR 0x03FDFC00 368c2ecf20Sopenharmony_ci#define ITVC_READ_DIR 0x0001FC00 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define MCI_MEMORY_DATA_BYTE0 0x00 398c2ecf20Sopenharmony_ci#define MCI_MEMORY_DATA_BYTE1 0x08 408c2ecf20Sopenharmony_ci#define MCI_MEMORY_DATA_BYTE2 0x10 418c2ecf20Sopenharmony_ci#define MCI_MEMORY_DATA_BYTE3 0x18 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define MCI_MEMORY_ADDRESS_BYTE2 0x20 448c2ecf20Sopenharmony_ci#define MCI_MEMORY_ADDRESS_BYTE1 0x28 458c2ecf20Sopenharmony_ci#define MCI_MEMORY_ADDRESS_BYTE0 0x30 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#define MCI_REGISTER_DATA_BYTE0 0x40 488c2ecf20Sopenharmony_ci#define MCI_REGISTER_DATA_BYTE1 0x48 498c2ecf20Sopenharmony_ci#define MCI_REGISTER_DATA_BYTE2 0x50 508c2ecf20Sopenharmony_ci#define MCI_REGISTER_DATA_BYTE3 0x58 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#define MCI_REGISTER_ADDRESS_BYTE0 0x60 538c2ecf20Sopenharmony_ci#define MCI_REGISTER_ADDRESS_BYTE1 0x68 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#define MCI_REGISTER_MODE 0x70 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* Read and write modes for polaris ITVC */ 588c2ecf20Sopenharmony_ci#define MCI_MODE_REGISTER_READ 0x000 598c2ecf20Sopenharmony_ci#define MCI_MODE_REGISTER_WRITE 0x100 608c2ecf20Sopenharmony_ci#define MCI_MODE_MEMORY_READ 0x000 618c2ecf20Sopenharmony_ci#define MCI_MODE_MEMORY_WRITE 0x4000 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic unsigned int mpeglines = 128; 648c2ecf20Sopenharmony_cimodule_param(mpeglines, int, 0644); 658c2ecf20Sopenharmony_ciMODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32"); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic unsigned int mpeglinesize = 512; 688c2ecf20Sopenharmony_cimodule_param(mpeglinesize, int, 0644); 698c2ecf20Sopenharmony_ciMODULE_PARM_DESC(mpeglinesize, 708c2ecf20Sopenharmony_ci "number of bytes in each line of an MPEG buffer, range 512-1024"); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic unsigned int v4l_debug = 1; 738c2ecf20Sopenharmony_cimodule_param(v4l_debug, int, 0644); 748c2ecf20Sopenharmony_ciMODULE_PARM_DESC(v4l_debug, "enable V4L debug messages"); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci#define dprintk(level, fmt, arg...) \ 778c2ecf20Sopenharmony_ci do { \ 788c2ecf20Sopenharmony_ci if (v4l_debug >= level) \ 798c2ecf20Sopenharmony_ci printk(KERN_DEBUG pr_fmt(fmt), ## arg); \ 808c2ecf20Sopenharmony_ci } while (0) 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic struct cx231xx_tvnorm cx231xx_tvnorms[] = { 838c2ecf20Sopenharmony_ci { 848c2ecf20Sopenharmony_ci .name = "NTSC-M", 858c2ecf20Sopenharmony_ci .id = V4L2_STD_NTSC_M, 868c2ecf20Sopenharmony_ci }, { 878c2ecf20Sopenharmony_ci .name = "NTSC-JP", 888c2ecf20Sopenharmony_ci .id = V4L2_STD_NTSC_M_JP, 898c2ecf20Sopenharmony_ci }, { 908c2ecf20Sopenharmony_ci .name = "PAL-BG", 918c2ecf20Sopenharmony_ci .id = V4L2_STD_PAL_BG, 928c2ecf20Sopenharmony_ci }, { 938c2ecf20Sopenharmony_ci .name = "PAL-DK", 948c2ecf20Sopenharmony_ci .id = V4L2_STD_PAL_DK, 958c2ecf20Sopenharmony_ci }, { 968c2ecf20Sopenharmony_ci .name = "PAL-I", 978c2ecf20Sopenharmony_ci .id = V4L2_STD_PAL_I, 988c2ecf20Sopenharmony_ci }, { 998c2ecf20Sopenharmony_ci .name = "PAL-M", 1008c2ecf20Sopenharmony_ci .id = V4L2_STD_PAL_M, 1018c2ecf20Sopenharmony_ci }, { 1028c2ecf20Sopenharmony_ci .name = "PAL-N", 1038c2ecf20Sopenharmony_ci .id = V4L2_STD_PAL_N, 1048c2ecf20Sopenharmony_ci }, { 1058c2ecf20Sopenharmony_ci .name = "PAL-Nc", 1068c2ecf20Sopenharmony_ci .id = V4L2_STD_PAL_Nc, 1078c2ecf20Sopenharmony_ci }, { 1088c2ecf20Sopenharmony_ci .name = "PAL-60", 1098c2ecf20Sopenharmony_ci .id = V4L2_STD_PAL_60, 1108c2ecf20Sopenharmony_ci }, { 1118c2ecf20Sopenharmony_ci .name = "SECAM-L", 1128c2ecf20Sopenharmony_ci .id = V4L2_STD_SECAM_L, 1138c2ecf20Sopenharmony_ci }, { 1148c2ecf20Sopenharmony_ci .name = "SECAM-DK", 1158c2ecf20Sopenharmony_ci .id = V4L2_STD_SECAM_DK, 1168c2ecf20Sopenharmony_ci } 1178c2ecf20Sopenharmony_ci}; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------ */ 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cienum cx231xx_capture_type { 1228c2ecf20Sopenharmony_ci CX231xx_MPEG_CAPTURE, 1238c2ecf20Sopenharmony_ci CX231xx_RAW_CAPTURE, 1248c2ecf20Sopenharmony_ci CX231xx_RAW_PASSTHRU_CAPTURE 1258c2ecf20Sopenharmony_ci}; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cienum cx231xx_capture_bits { 1288c2ecf20Sopenharmony_ci CX231xx_RAW_BITS_NONE = 0x00, 1298c2ecf20Sopenharmony_ci CX231xx_RAW_BITS_YUV_CAPTURE = 0x01, 1308c2ecf20Sopenharmony_ci CX231xx_RAW_BITS_PCM_CAPTURE = 0x02, 1318c2ecf20Sopenharmony_ci CX231xx_RAW_BITS_VBI_CAPTURE = 0x04, 1328c2ecf20Sopenharmony_ci CX231xx_RAW_BITS_PASSTHRU_CAPTURE = 0x08, 1338c2ecf20Sopenharmony_ci CX231xx_RAW_BITS_TO_HOST_CAPTURE = 0x10 1348c2ecf20Sopenharmony_ci}; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cienum cx231xx_capture_end { 1378c2ecf20Sopenharmony_ci CX231xx_END_AT_GOP, /* stop at the end of gop, generate irq */ 1388c2ecf20Sopenharmony_ci CX231xx_END_NOW, /* stop immediately, no irq */ 1398c2ecf20Sopenharmony_ci}; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cienum cx231xx_framerate { 1428c2ecf20Sopenharmony_ci CX231xx_FRAMERATE_NTSC_30, /* NTSC: 30fps */ 1438c2ecf20Sopenharmony_ci CX231xx_FRAMERATE_PAL_25 /* PAL: 25fps */ 1448c2ecf20Sopenharmony_ci}; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cienum cx231xx_stream_port { 1478c2ecf20Sopenharmony_ci CX231xx_OUTPUT_PORT_MEMORY, 1488c2ecf20Sopenharmony_ci CX231xx_OUTPUT_PORT_STREAMING, 1498c2ecf20Sopenharmony_ci CX231xx_OUTPUT_PORT_SERIAL 1508c2ecf20Sopenharmony_ci}; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cienum cx231xx_data_xfer_status { 1538c2ecf20Sopenharmony_ci CX231xx_MORE_BUFFERS_FOLLOW, 1548c2ecf20Sopenharmony_ci CX231xx_LAST_BUFFER, 1558c2ecf20Sopenharmony_ci}; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cienum cx231xx_picture_mask { 1588c2ecf20Sopenharmony_ci CX231xx_PICTURE_MASK_NONE, 1598c2ecf20Sopenharmony_ci CX231xx_PICTURE_MASK_I_FRAMES, 1608c2ecf20Sopenharmony_ci CX231xx_PICTURE_MASK_I_P_FRAMES = 0x3, 1618c2ecf20Sopenharmony_ci CX231xx_PICTURE_MASK_ALL_FRAMES = 0x7, 1628c2ecf20Sopenharmony_ci}; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cienum cx231xx_vbi_mode_bits { 1658c2ecf20Sopenharmony_ci CX231xx_VBI_BITS_SLICED, 1668c2ecf20Sopenharmony_ci CX231xx_VBI_BITS_RAW, 1678c2ecf20Sopenharmony_ci}; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cienum cx231xx_vbi_insertion_bits { 1708c2ecf20Sopenharmony_ci CX231xx_VBI_BITS_INSERT_IN_XTENSION_USR_DATA, 1718c2ecf20Sopenharmony_ci CX231xx_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1, 1728c2ecf20Sopenharmony_ci CX231xx_VBI_BITS_SEPARATE_STREAM = 0x2 << 1, 1738c2ecf20Sopenharmony_ci CX231xx_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1, 1748c2ecf20Sopenharmony_ci CX231xx_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1, 1758c2ecf20Sopenharmony_ci}; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cienum cx231xx_dma_unit { 1788c2ecf20Sopenharmony_ci CX231xx_DMA_BYTES, 1798c2ecf20Sopenharmony_ci CX231xx_DMA_FRAMES, 1808c2ecf20Sopenharmony_ci}; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cienum cx231xx_dma_transfer_status_bits { 1838c2ecf20Sopenharmony_ci CX231xx_DMA_TRANSFER_BITS_DONE = 0x01, 1848c2ecf20Sopenharmony_ci CX231xx_DMA_TRANSFER_BITS_ERROR = 0x04, 1858c2ecf20Sopenharmony_ci CX231xx_DMA_TRANSFER_BITS_LL_ERROR = 0x10, 1868c2ecf20Sopenharmony_ci}; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cienum cx231xx_pause { 1898c2ecf20Sopenharmony_ci CX231xx_PAUSE_ENCODING, 1908c2ecf20Sopenharmony_ci CX231xx_RESUME_ENCODING, 1918c2ecf20Sopenharmony_ci}; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cienum cx231xx_copyright { 1948c2ecf20Sopenharmony_ci CX231xx_COPYRIGHT_OFF, 1958c2ecf20Sopenharmony_ci CX231xx_COPYRIGHT_ON, 1968c2ecf20Sopenharmony_ci}; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cienum cx231xx_notification_type { 1998c2ecf20Sopenharmony_ci CX231xx_NOTIFICATION_REFRESH, 2008c2ecf20Sopenharmony_ci}; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cienum cx231xx_notification_status { 2038c2ecf20Sopenharmony_ci CX231xx_NOTIFICATION_OFF, 2048c2ecf20Sopenharmony_ci CX231xx_NOTIFICATION_ON, 2058c2ecf20Sopenharmony_ci}; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cienum cx231xx_notification_mailbox { 2088c2ecf20Sopenharmony_ci CX231xx_NOTIFICATION_NO_MAILBOX = -1, 2098c2ecf20Sopenharmony_ci}; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cienum cx231xx_field1_lines { 2128c2ecf20Sopenharmony_ci CX231xx_FIELD1_SAA7114 = 0x00EF, /* 239 */ 2138c2ecf20Sopenharmony_ci CX231xx_FIELD1_SAA7115 = 0x00F0, /* 240 */ 2148c2ecf20Sopenharmony_ci CX231xx_FIELD1_MICRONAS = 0x0105, /* 261 */ 2158c2ecf20Sopenharmony_ci}; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_cienum cx231xx_field2_lines { 2188c2ecf20Sopenharmony_ci CX231xx_FIELD2_SAA7114 = 0x00EF, /* 239 */ 2198c2ecf20Sopenharmony_ci CX231xx_FIELD2_SAA7115 = 0x00F0, /* 240 */ 2208c2ecf20Sopenharmony_ci CX231xx_FIELD2_MICRONAS = 0x0106, /* 262 */ 2218c2ecf20Sopenharmony_ci}; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_cienum cx231xx_custom_data_type { 2248c2ecf20Sopenharmony_ci CX231xx_CUSTOM_EXTENSION_USR_DATA, 2258c2ecf20Sopenharmony_ci CX231xx_CUSTOM_PRIVATE_PACKET, 2268c2ecf20Sopenharmony_ci}; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cienum cx231xx_mute { 2298c2ecf20Sopenharmony_ci CX231xx_UNMUTE, 2308c2ecf20Sopenharmony_ci CX231xx_MUTE, 2318c2ecf20Sopenharmony_ci}; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_cienum cx231xx_mute_video_mask { 2348c2ecf20Sopenharmony_ci CX231xx_MUTE_VIDEO_V_MASK = 0x0000FF00, 2358c2ecf20Sopenharmony_ci CX231xx_MUTE_VIDEO_U_MASK = 0x00FF0000, 2368c2ecf20Sopenharmony_ci CX231xx_MUTE_VIDEO_Y_MASK = 0xFF000000, 2378c2ecf20Sopenharmony_ci}; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_cienum cx231xx_mute_video_shift { 2408c2ecf20Sopenharmony_ci CX231xx_MUTE_VIDEO_V_SHIFT = 8, 2418c2ecf20Sopenharmony_ci CX231xx_MUTE_VIDEO_U_SHIFT = 16, 2428c2ecf20Sopenharmony_ci CX231xx_MUTE_VIDEO_Y_SHIFT = 24, 2438c2ecf20Sopenharmony_ci}; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci/* defines below are from ivtv-driver.h */ 2468c2ecf20Sopenharmony_ci#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci/* Firmware API commands */ 2498c2ecf20Sopenharmony_ci#define IVTV_API_STD_TIMEOUT 500 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci/* Registers */ 2528c2ecf20Sopenharmony_ci/* IVTV_REG_OFFSET */ 2538c2ecf20Sopenharmony_ci#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8) 2548c2ecf20Sopenharmony_ci#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC) 2558c2ecf20Sopenharmony_ci#define IVTV_REG_SPU (0x9050) 2568c2ecf20Sopenharmony_ci#define IVTV_REG_HW_BLOCKS (0x9054) 2578c2ecf20Sopenharmony_ci#define IVTV_REG_VPU (0x9058) 2588c2ecf20Sopenharmony_ci#define IVTV_REG_APU (0xA064) 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci/* 2618c2ecf20Sopenharmony_ci * Bit definitions for MC417_RWD and MC417_OEN registers 2628c2ecf20Sopenharmony_ci * 2638c2ecf20Sopenharmony_ci * bits 31-16 2648c2ecf20Sopenharmony_ci *+-----------+ 2658c2ecf20Sopenharmony_ci *| Reserved | 2668c2ecf20Sopenharmony_ci *|+-----------+ 2678c2ecf20Sopenharmony_ci *| bit 15 bit 14 bit 13 bit 12 bit 11 bit 10 bit 9 bit 8 2688c2ecf20Sopenharmony_ci *|+-------+-------+-------+-------+-------+-------+-------+-------+ 2698c2ecf20Sopenharmony_ci *|| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0| 2708c2ecf20Sopenharmony_ci *|+-------+-------+-------+-------+-------+-------+-------+-------+ 2718c2ecf20Sopenharmony_ci *| bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 2728c2ecf20Sopenharmony_ci *|+-------+-------+-------+-------+-------+-------+-------+-------+ 2738c2ecf20Sopenharmony_ci *||MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0| 2748c2ecf20Sopenharmony_ci *|+-------+-------+-------+-------+-------+-------+-------+-------+ 2758c2ecf20Sopenharmony_ci */ 2768c2ecf20Sopenharmony_ci#define MC417_MIWR 0x8000 2778c2ecf20Sopenharmony_ci#define MC417_MIRD 0x4000 2788c2ecf20Sopenharmony_ci#define MC417_MICS 0x2000 2798c2ecf20Sopenharmony_ci#define MC417_MIRDY 0x1000 2808c2ecf20Sopenharmony_ci#define MC417_MIADDR 0x0F00 2818c2ecf20Sopenharmony_ci#define MC417_MIDATA 0x00FF 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci/* Bit definitions for MC417_CTL register **** 2858c2ecf20Sopenharmony_ci *bits 31-6 bits 5-4 bit 3 bits 2-1 Bit 0 2868c2ecf20Sopenharmony_ci *+--------+-------------+--------+--------------+------------+ 2878c2ecf20Sopenharmony_ci *|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN| 2888c2ecf20Sopenharmony_ci *+--------+-------------+--------+--------------+------------+ 2898c2ecf20Sopenharmony_ci */ 2908c2ecf20Sopenharmony_ci#define MC417_SPD_CTL(x) (((x) << 4) & 0x00000030) 2918c2ecf20Sopenharmony_ci#define MC417_GPIO_SEL(x) (((x) << 1) & 0x00000006) 2928c2ecf20Sopenharmony_ci#define MC417_UART_GPIO_EN 0x00000001 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci/* Values for speed control */ 2958c2ecf20Sopenharmony_ci#define MC417_SPD_CTL_SLOW 0x1 2968c2ecf20Sopenharmony_ci#define MC417_SPD_CTL_MEDIUM 0x0 2978c2ecf20Sopenharmony_ci#define MC417_SPD_CTL_FAST 0x3 /* b'1x, but we use b'11 */ 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci/* Values for GPIO select */ 3008c2ecf20Sopenharmony_ci#define MC417_GPIO_SEL_GPIO3 0x3 3018c2ecf20Sopenharmony_ci#define MC417_GPIO_SEL_GPIO2 0x2 3028c2ecf20Sopenharmony_ci#define MC417_GPIO_SEL_GPIO1 0x1 3038c2ecf20Sopenharmony_ci#define MC417_GPIO_SEL_GPIO0 0x0 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci#define CX23417_GPIO_MASK 0xFC0003FF 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cistatic int set_itvc_reg(struct cx231xx *dev, u32 gpio_direction, u32 value) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci int status = 0; 3118c2ecf20Sopenharmony_ci u32 _gpio_direction = 0; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci _gpio_direction = _gpio_direction & CX23417_GPIO_MASK; 3148c2ecf20Sopenharmony_ci _gpio_direction = _gpio_direction | gpio_direction; 3158c2ecf20Sopenharmony_ci status = cx231xx_send_gpio_cmd(dev, _gpio_direction, 3168c2ecf20Sopenharmony_ci (u8 *)&value, 4, 0, 0); 3178c2ecf20Sopenharmony_ci return status; 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cistatic int get_itvc_reg(struct cx231xx *dev, u32 gpio_direction, u32 *val_ptr) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci int status = 0; 3238c2ecf20Sopenharmony_ci u32 _gpio_direction = 0; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci _gpio_direction = _gpio_direction & CX23417_GPIO_MASK; 3268c2ecf20Sopenharmony_ci _gpio_direction = _gpio_direction | gpio_direction; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci status = cx231xx_send_gpio_cmd(dev, _gpio_direction, 3298c2ecf20Sopenharmony_ci (u8 *)val_ptr, 4, 0, 1); 3308c2ecf20Sopenharmony_ci return status; 3318c2ecf20Sopenharmony_ci} 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cistatic int wait_for_mci_complete(struct cx231xx *dev) 3348c2ecf20Sopenharmony_ci{ 3358c2ecf20Sopenharmony_ci u32 gpio; 3368c2ecf20Sopenharmony_ci u32 gpio_direction = 0; 3378c2ecf20Sopenharmony_ci u8 count = 0; 3388c2ecf20Sopenharmony_ci get_itvc_reg(dev, gpio_direction, &gpio); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci while (!(gpio&0x020000)) { 3418c2ecf20Sopenharmony_ci msleep(10); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci get_itvc_reg(dev, gpio_direction, &gpio); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci if (count++ > 100) { 3468c2ecf20Sopenharmony_ci dprintk(3, "ERROR: Timeout - gpio=%x\n", gpio); 3478c2ecf20Sopenharmony_ci return -EIO; 3488c2ecf20Sopenharmony_ci } 3498c2ecf20Sopenharmony_ci } 3508c2ecf20Sopenharmony_ci return 0; 3518c2ecf20Sopenharmony_ci} 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_cistatic int mc417_register_write(struct cx231xx *dev, u16 address, u32 value) 3548c2ecf20Sopenharmony_ci{ 3558c2ecf20Sopenharmony_ci u32 temp; 3568c2ecf20Sopenharmony_ci int status = 0; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci temp = 0x82 | MCI_REGISTER_DATA_BYTE0 | ((value & 0x000000FF) << 8); 3598c2ecf20Sopenharmony_ci temp = temp << 10; 3608c2ecf20Sopenharmony_ci status = set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 3618c2ecf20Sopenharmony_ci if (status < 0) 3628c2ecf20Sopenharmony_ci return status; 3638c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 3648c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci /*write data byte 1;*/ 3678c2ecf20Sopenharmony_ci temp = 0x82 | MCI_REGISTER_DATA_BYTE1 | (value & 0x0000FF00); 3688c2ecf20Sopenharmony_ci temp = temp << 10; 3698c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 3708c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 3718c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci /*write data byte 2;*/ 3748c2ecf20Sopenharmony_ci temp = 0x82 | MCI_REGISTER_DATA_BYTE2 | ((value & 0x00FF0000) >> 8); 3758c2ecf20Sopenharmony_ci temp = temp << 10; 3768c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 3778c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 3788c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci /*write data byte 3;*/ 3818c2ecf20Sopenharmony_ci temp = 0x82 | MCI_REGISTER_DATA_BYTE3 | ((value & 0xFF000000) >> 16); 3828c2ecf20Sopenharmony_ci temp = temp << 10; 3838c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 3848c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 3858c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci /*write address byte 0;*/ 3888c2ecf20Sopenharmony_ci temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE0 | ((address & 0x000000FF) << 8); 3898c2ecf20Sopenharmony_ci temp = temp << 10; 3908c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 3918c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 3928c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci /*write address byte 1;*/ 3958c2ecf20Sopenharmony_ci temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE1 | (address & 0x0000FF00); 3968c2ecf20Sopenharmony_ci temp = temp << 10; 3978c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 3988c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 3998c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci /*Write that the mode is write.*/ 4028c2ecf20Sopenharmony_ci temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_WRITE; 4038c2ecf20Sopenharmony_ci temp = temp << 10; 4048c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 4058c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 4068c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci return wait_for_mci_complete(dev); 4098c2ecf20Sopenharmony_ci} 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_cistatic int mc417_register_read(struct cx231xx *dev, u16 address, u32 *value) 4128c2ecf20Sopenharmony_ci{ 4138c2ecf20Sopenharmony_ci /*write address byte 0;*/ 4148c2ecf20Sopenharmony_ci u32 temp; 4158c2ecf20Sopenharmony_ci u32 return_value = 0; 4168c2ecf20Sopenharmony_ci int ret = 0; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE0 | ((address & 0x00FF) << 8); 4198c2ecf20Sopenharmony_ci temp = temp << 10; 4208c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 4218c2ecf20Sopenharmony_ci temp = temp | ((0x05) << 10); 4228c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci /*write address byte 1;*/ 4258c2ecf20Sopenharmony_ci temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE1 | (address & 0xFF00); 4268c2ecf20Sopenharmony_ci temp = temp << 10; 4278c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 4288c2ecf20Sopenharmony_ci temp = temp | ((0x05) << 10); 4298c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci /*write that the mode is read;*/ 4328c2ecf20Sopenharmony_ci temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_READ; 4338c2ecf20Sopenharmony_ci temp = temp << 10; 4348c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 4358c2ecf20Sopenharmony_ci temp = temp | ((0x05) << 10); 4368c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci /*wait for the MIRDY line to be asserted , 4398c2ecf20Sopenharmony_ci signalling that the read is done;*/ 4408c2ecf20Sopenharmony_ci ret = wait_for_mci_complete(dev); 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci /*switch the DATA- GPIO to input mode;*/ 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci /*Read data byte 0;*/ 4458c2ecf20Sopenharmony_ci temp = (0x82 | MCI_REGISTER_DATA_BYTE0) << 10; 4468c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 4478c2ecf20Sopenharmony_ci temp = ((0x81 | MCI_REGISTER_DATA_BYTE0) << 10); 4488c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 4498c2ecf20Sopenharmony_ci get_itvc_reg(dev, ITVC_READ_DIR, &temp); 4508c2ecf20Sopenharmony_ci return_value |= ((temp & 0x03FC0000) >> 18); 4518c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10)); 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci /* Read data byte 1;*/ 4548c2ecf20Sopenharmony_ci temp = (0x82 | MCI_REGISTER_DATA_BYTE1) << 10; 4558c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 4568c2ecf20Sopenharmony_ci temp = ((0x81 | MCI_REGISTER_DATA_BYTE1) << 10); 4578c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 4588c2ecf20Sopenharmony_ci get_itvc_reg(dev, ITVC_READ_DIR, &temp); 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci return_value |= ((temp & 0x03FC0000) >> 10); 4618c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10)); 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci /*Read data byte 2;*/ 4648c2ecf20Sopenharmony_ci temp = (0x82 | MCI_REGISTER_DATA_BYTE2) << 10; 4658c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 4668c2ecf20Sopenharmony_ci temp = ((0x81 | MCI_REGISTER_DATA_BYTE2) << 10); 4678c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 4688c2ecf20Sopenharmony_ci get_itvc_reg(dev, ITVC_READ_DIR, &temp); 4698c2ecf20Sopenharmony_ci return_value |= ((temp & 0x03FC0000) >> 2); 4708c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10)); 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci /*Read data byte 3;*/ 4738c2ecf20Sopenharmony_ci temp = (0x82 | MCI_REGISTER_DATA_BYTE3) << 10; 4748c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 4758c2ecf20Sopenharmony_ci temp = ((0x81 | MCI_REGISTER_DATA_BYTE3) << 10); 4768c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 4778c2ecf20Sopenharmony_ci get_itvc_reg(dev, ITVC_READ_DIR, &temp); 4788c2ecf20Sopenharmony_ci return_value |= ((temp & 0x03FC0000) << 6); 4798c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10)); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci *value = return_value; 4828c2ecf20Sopenharmony_ci return ret; 4838c2ecf20Sopenharmony_ci} 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_cistatic int mc417_memory_write(struct cx231xx *dev, u32 address, u32 value) 4868c2ecf20Sopenharmony_ci{ 4878c2ecf20Sopenharmony_ci /*write data byte 0;*/ 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci u32 temp; 4908c2ecf20Sopenharmony_ci int ret = 0; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_DATA_BYTE0 | ((value & 0x000000FF) << 8); 4938c2ecf20Sopenharmony_ci temp = temp << 10; 4948c2ecf20Sopenharmony_ci ret = set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 4958c2ecf20Sopenharmony_ci if (ret < 0) 4968c2ecf20Sopenharmony_ci return ret; 4978c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 4988c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci /*write data byte 1;*/ 5018c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_DATA_BYTE1 | (value & 0x0000FF00); 5028c2ecf20Sopenharmony_ci temp = temp << 10; 5038c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5048c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 5058c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci /*write data byte 2;*/ 5088c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_DATA_BYTE2 | ((value & 0x00FF0000) >> 8); 5098c2ecf20Sopenharmony_ci temp = temp << 10; 5108c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5118c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 5128c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci /*write data byte 3;*/ 5158c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_DATA_BYTE3 | ((value & 0xFF000000) >> 16); 5168c2ecf20Sopenharmony_ci temp = temp << 10; 5178c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5188c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 5198c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci /* write address byte 2;*/ 5228c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE | 5238c2ecf20Sopenharmony_ci ((address & 0x003F0000) >> 8); 5248c2ecf20Sopenharmony_ci temp = temp << 10; 5258c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5268c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 5278c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci /* write address byte 1;*/ 5308c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00); 5318c2ecf20Sopenharmony_ci temp = temp << 10; 5328c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5338c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 5348c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci /* write address byte 0;*/ 5378c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF) << 8); 5388c2ecf20Sopenharmony_ci temp = temp << 10; 5398c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5408c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 5418c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci /*wait for MIRDY line;*/ 5448c2ecf20Sopenharmony_ci wait_for_mci_complete(dev); 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci return 0; 5478c2ecf20Sopenharmony_ci} 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_cistatic int mc417_memory_read(struct cx231xx *dev, u32 address, u32 *value) 5508c2ecf20Sopenharmony_ci{ 5518c2ecf20Sopenharmony_ci u32 temp = 0; 5528c2ecf20Sopenharmony_ci u32 return_value = 0; 5538c2ecf20Sopenharmony_ci int ret = 0; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci /*write address byte 2;*/ 5568c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_READ | 5578c2ecf20Sopenharmony_ci ((address & 0x003F0000) >> 8); 5588c2ecf20Sopenharmony_ci temp = temp << 10; 5598c2ecf20Sopenharmony_ci ret = set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5608c2ecf20Sopenharmony_ci if (ret < 0) 5618c2ecf20Sopenharmony_ci return ret; 5628c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 5638c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci /*write address byte 1*/ 5668c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00); 5678c2ecf20Sopenharmony_ci temp = temp << 10; 5688c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5698c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 5708c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci /*write address byte 0*/ 5738c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF) << 8); 5748c2ecf20Sopenharmony_ci temp = temp << 10; 5758c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5768c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 5778c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_WRITE_DIR, temp); 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci /*Wait for MIRDY line*/ 5808c2ecf20Sopenharmony_ci ret = wait_for_mci_complete(dev); 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci /*Read data byte 3;*/ 5848c2ecf20Sopenharmony_ci temp = (0x82 | MCI_MEMORY_DATA_BYTE3) << 10; 5858c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 5868c2ecf20Sopenharmony_ci temp = ((0x81 | MCI_MEMORY_DATA_BYTE3) << 10); 5878c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 5888c2ecf20Sopenharmony_ci get_itvc_reg(dev, ITVC_READ_DIR, &temp); 5898c2ecf20Sopenharmony_ci return_value |= ((temp & 0x03FC0000) << 6); 5908c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10)); 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci /*Read data byte 2;*/ 5938c2ecf20Sopenharmony_ci temp = (0x82 | MCI_MEMORY_DATA_BYTE2) << 10; 5948c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 5958c2ecf20Sopenharmony_ci temp = ((0x81 | MCI_MEMORY_DATA_BYTE2) << 10); 5968c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 5978c2ecf20Sopenharmony_ci get_itvc_reg(dev, ITVC_READ_DIR, &temp); 5988c2ecf20Sopenharmony_ci return_value |= ((temp & 0x03FC0000) >> 2); 5998c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10)); 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci /* Read data byte 1;*/ 6028c2ecf20Sopenharmony_ci temp = (0x82 | MCI_MEMORY_DATA_BYTE1) << 10; 6038c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 6048c2ecf20Sopenharmony_ci temp = ((0x81 | MCI_MEMORY_DATA_BYTE1) << 10); 6058c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 6068c2ecf20Sopenharmony_ci get_itvc_reg(dev, ITVC_READ_DIR, &temp); 6078c2ecf20Sopenharmony_ci return_value |= ((temp & 0x03FC0000) >> 10); 6088c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10)); 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci /*Read data byte 0;*/ 6118c2ecf20Sopenharmony_ci temp = (0x82 | MCI_MEMORY_DATA_BYTE0) << 10; 6128c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 6138c2ecf20Sopenharmony_ci temp = ((0x81 | MCI_MEMORY_DATA_BYTE0) << 10); 6148c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, temp); 6158c2ecf20Sopenharmony_ci get_itvc_reg(dev, ITVC_READ_DIR, &temp); 6168c2ecf20Sopenharmony_ci return_value |= ((temp & 0x03FC0000) >> 18); 6178c2ecf20Sopenharmony_ci set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10)); 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci *value = return_value; 6208c2ecf20Sopenharmony_ci return ret; 6218c2ecf20Sopenharmony_ci} 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------ */ 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci/* MPEG encoder API */ 6268c2ecf20Sopenharmony_cistatic char *cmd_to_str(int cmd) 6278c2ecf20Sopenharmony_ci{ 6288c2ecf20Sopenharmony_ci switch (cmd) { 6298c2ecf20Sopenharmony_ci case CX2341X_ENC_PING_FW: 6308c2ecf20Sopenharmony_ci return "PING_FW"; 6318c2ecf20Sopenharmony_ci case CX2341X_ENC_START_CAPTURE: 6328c2ecf20Sopenharmony_ci return "START_CAPTURE"; 6338c2ecf20Sopenharmony_ci case CX2341X_ENC_STOP_CAPTURE: 6348c2ecf20Sopenharmony_ci return "STOP_CAPTURE"; 6358c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_AUDIO_ID: 6368c2ecf20Sopenharmony_ci return "SET_AUDIO_ID"; 6378c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_VIDEO_ID: 6388c2ecf20Sopenharmony_ci return "SET_VIDEO_ID"; 6398c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_PCR_ID: 6408c2ecf20Sopenharmony_ci return "SET_PCR_PID"; 6418c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_FRAME_RATE: 6428c2ecf20Sopenharmony_ci return "SET_FRAME_RATE"; 6438c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_FRAME_SIZE: 6448c2ecf20Sopenharmony_ci return "SET_FRAME_SIZE"; 6458c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_BIT_RATE: 6468c2ecf20Sopenharmony_ci return "SET_BIT_RATE"; 6478c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_GOP_PROPERTIES: 6488c2ecf20Sopenharmony_ci return "SET_GOP_PROPERTIES"; 6498c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_ASPECT_RATIO: 6508c2ecf20Sopenharmony_ci return "SET_ASPECT_RATIO"; 6518c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_DNR_FILTER_MODE: 6528c2ecf20Sopenharmony_ci return "SET_DNR_FILTER_PROPS"; 6538c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_DNR_FILTER_PROPS: 6548c2ecf20Sopenharmony_ci return "SET_DNR_FILTER_PROPS"; 6558c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_CORING_LEVELS: 6568c2ecf20Sopenharmony_ci return "SET_CORING_LEVELS"; 6578c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE: 6588c2ecf20Sopenharmony_ci return "SET_SPATIAL_FILTER_TYPE"; 6598c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_VBI_LINE: 6608c2ecf20Sopenharmony_ci return "SET_VBI_LINE"; 6618c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_STREAM_TYPE: 6628c2ecf20Sopenharmony_ci return "SET_STREAM_TYPE"; 6638c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_OUTPUT_PORT: 6648c2ecf20Sopenharmony_ci return "SET_OUTPUT_PORT"; 6658c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_AUDIO_PROPERTIES: 6668c2ecf20Sopenharmony_ci return "SET_AUDIO_PROPERTIES"; 6678c2ecf20Sopenharmony_ci case CX2341X_ENC_HALT_FW: 6688c2ecf20Sopenharmony_ci return "HALT_FW"; 6698c2ecf20Sopenharmony_ci case CX2341X_ENC_GET_VERSION: 6708c2ecf20Sopenharmony_ci return "GET_VERSION"; 6718c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_GOP_CLOSURE: 6728c2ecf20Sopenharmony_ci return "SET_GOP_CLOSURE"; 6738c2ecf20Sopenharmony_ci case CX2341X_ENC_GET_SEQ_END: 6748c2ecf20Sopenharmony_ci return "GET_SEQ_END"; 6758c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_PGM_INDEX_INFO: 6768c2ecf20Sopenharmony_ci return "SET_PGM_INDEX_INFO"; 6778c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_VBI_CONFIG: 6788c2ecf20Sopenharmony_ci return "SET_VBI_CONFIG"; 6798c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_DMA_BLOCK_SIZE: 6808c2ecf20Sopenharmony_ci return "SET_DMA_BLOCK_SIZE"; 6818c2ecf20Sopenharmony_ci case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10: 6828c2ecf20Sopenharmony_ci return "GET_PREV_DMA_INFO_MB_10"; 6838c2ecf20Sopenharmony_ci case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9: 6848c2ecf20Sopenharmony_ci return "GET_PREV_DMA_INFO_MB_9"; 6858c2ecf20Sopenharmony_ci case CX2341X_ENC_SCHED_DMA_TO_HOST: 6868c2ecf20Sopenharmony_ci return "SCHED_DMA_TO_HOST"; 6878c2ecf20Sopenharmony_ci case CX2341X_ENC_INITIALIZE_INPUT: 6888c2ecf20Sopenharmony_ci return "INITIALIZE_INPUT"; 6898c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_FRAME_DROP_RATE: 6908c2ecf20Sopenharmony_ci return "SET_FRAME_DROP_RATE"; 6918c2ecf20Sopenharmony_ci case CX2341X_ENC_PAUSE_ENCODER: 6928c2ecf20Sopenharmony_ci return "PAUSE_ENCODER"; 6938c2ecf20Sopenharmony_ci case CX2341X_ENC_REFRESH_INPUT: 6948c2ecf20Sopenharmony_ci return "REFRESH_INPUT"; 6958c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_COPYRIGHT: 6968c2ecf20Sopenharmony_ci return "SET_COPYRIGHT"; 6978c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_EVENT_NOTIFICATION: 6988c2ecf20Sopenharmony_ci return "SET_EVENT_NOTIFICATION"; 6998c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_NUM_VSYNC_LINES: 7008c2ecf20Sopenharmony_ci return "SET_NUM_VSYNC_LINES"; 7018c2ecf20Sopenharmony_ci case CX2341X_ENC_SET_PLACEHOLDER: 7028c2ecf20Sopenharmony_ci return "SET_PLACEHOLDER"; 7038c2ecf20Sopenharmony_ci case CX2341X_ENC_MUTE_VIDEO: 7048c2ecf20Sopenharmony_ci return "MUTE_VIDEO"; 7058c2ecf20Sopenharmony_ci case CX2341X_ENC_MUTE_AUDIO: 7068c2ecf20Sopenharmony_ci return "MUTE_AUDIO"; 7078c2ecf20Sopenharmony_ci case CX2341X_ENC_MISC: 7088c2ecf20Sopenharmony_ci return "MISC"; 7098c2ecf20Sopenharmony_ci default: 7108c2ecf20Sopenharmony_ci return "UNKNOWN"; 7118c2ecf20Sopenharmony_ci } 7128c2ecf20Sopenharmony_ci} 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_cistatic int cx231xx_mbox_func(void *priv, u32 command, int in, int out, 7158c2ecf20Sopenharmony_ci u32 data[CX2341X_MBOX_MAX_DATA]) 7168c2ecf20Sopenharmony_ci{ 7178c2ecf20Sopenharmony_ci struct cx231xx *dev = priv; 7188c2ecf20Sopenharmony_ci unsigned long timeout; 7198c2ecf20Sopenharmony_ci u32 value, flag, retval = 0; 7208c2ecf20Sopenharmony_ci int i; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci dprintk(3, "%s: command(0x%X) = %s\n", __func__, command, 7238c2ecf20Sopenharmony_ci cmd_to_str(command)); 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci /* this may not be 100% safe if we can't read any memory location 7268c2ecf20Sopenharmony_ci without side effects */ 7278c2ecf20Sopenharmony_ci mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value); 7288c2ecf20Sopenharmony_ci if (value != 0x12345678) { 7298c2ecf20Sopenharmony_ci dprintk(3, "Firmware and/or mailbox pointer not initialized or corrupted, signature = 0x%x, cmd = %s\n", 7308c2ecf20Sopenharmony_ci value, cmd_to_str(command)); 7318c2ecf20Sopenharmony_ci return -EIO; 7328c2ecf20Sopenharmony_ci } 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci /* This read looks at 32 bits, but flag is only 8 bits. 7358c2ecf20Sopenharmony_ci * Seems we also bail if CMD or TIMEOUT bytes are set??? 7368c2ecf20Sopenharmony_ci */ 7378c2ecf20Sopenharmony_ci mc417_memory_read(dev, dev->cx23417_mailbox, &flag); 7388c2ecf20Sopenharmony_ci if (flag) { 7398c2ecf20Sopenharmony_ci dprintk(3, "ERROR: Mailbox appears to be in use (%x), cmd = %s\n", 7408c2ecf20Sopenharmony_ci flag, cmd_to_str(command)); 7418c2ecf20Sopenharmony_ci return -EBUSY; 7428c2ecf20Sopenharmony_ci } 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci flag |= 1; /* tell 'em we're working on it */ 7458c2ecf20Sopenharmony_ci mc417_memory_write(dev, dev->cx23417_mailbox, flag); 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci /* write command + args + fill remaining with zeros */ 7488c2ecf20Sopenharmony_ci /* command code */ 7498c2ecf20Sopenharmony_ci mc417_memory_write(dev, dev->cx23417_mailbox + 1, command); 7508c2ecf20Sopenharmony_ci mc417_memory_write(dev, dev->cx23417_mailbox + 3, 7518c2ecf20Sopenharmony_ci IVTV_API_STD_TIMEOUT); /* timeout */ 7528c2ecf20Sopenharmony_ci for (i = 0; i < in; i++) { 7538c2ecf20Sopenharmony_ci mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]); 7548c2ecf20Sopenharmony_ci dprintk(3, "API Input %d = %d\n", i, data[i]); 7558c2ecf20Sopenharmony_ci } 7568c2ecf20Sopenharmony_ci for (; i < CX2341X_MBOX_MAX_DATA; i++) 7578c2ecf20Sopenharmony_ci mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0); 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci flag |= 3; /* tell 'em we're done writing */ 7608c2ecf20Sopenharmony_ci mc417_memory_write(dev, dev->cx23417_mailbox, flag); 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci /* wait for firmware to handle the API command */ 7638c2ecf20Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(10); 7648c2ecf20Sopenharmony_ci for (;;) { 7658c2ecf20Sopenharmony_ci mc417_memory_read(dev, dev->cx23417_mailbox, &flag); 7668c2ecf20Sopenharmony_ci if (0 != (flag & 4)) 7678c2ecf20Sopenharmony_ci break; 7688c2ecf20Sopenharmony_ci if (time_after(jiffies, timeout)) { 7698c2ecf20Sopenharmony_ci dprintk(3, "ERROR: API Mailbox timeout\n"); 7708c2ecf20Sopenharmony_ci return -EIO; 7718c2ecf20Sopenharmony_ci } 7728c2ecf20Sopenharmony_ci udelay(10); 7738c2ecf20Sopenharmony_ci } 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci /* read output values */ 7768c2ecf20Sopenharmony_ci for (i = 0; i < out; i++) { 7778c2ecf20Sopenharmony_ci mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i); 7788c2ecf20Sopenharmony_ci dprintk(3, "API Output %d = %d\n", i, data[i]); 7798c2ecf20Sopenharmony_ci } 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval); 7828c2ecf20Sopenharmony_ci dprintk(3, "API result = %d\n", retval); 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci flag = 0; 7858c2ecf20Sopenharmony_ci mc417_memory_write(dev, dev->cx23417_mailbox, flag); 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci return 0; 7888c2ecf20Sopenharmony_ci} 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci/* We don't need to call the API often, so using just one 7918c2ecf20Sopenharmony_ci * mailbox will probably suffice 7928c2ecf20Sopenharmony_ci */ 7938c2ecf20Sopenharmony_cistatic int cx231xx_api_cmd(struct cx231xx *dev, u32 command, 7948c2ecf20Sopenharmony_ci u32 inputcnt, u32 outputcnt, ...) 7958c2ecf20Sopenharmony_ci{ 7968c2ecf20Sopenharmony_ci u32 data[CX2341X_MBOX_MAX_DATA]; 7978c2ecf20Sopenharmony_ci va_list vargs; 7988c2ecf20Sopenharmony_ci int i, err; 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci dprintk(3, "%s() cmds = 0x%08x\n", __func__, command); 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci va_start(vargs, outputcnt); 8038c2ecf20Sopenharmony_ci for (i = 0; i < inputcnt; i++) 8048c2ecf20Sopenharmony_ci data[i] = va_arg(vargs, int); 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci err = cx231xx_mbox_func(dev, command, inputcnt, outputcnt, data); 8078c2ecf20Sopenharmony_ci for (i = 0; i < outputcnt; i++) { 8088c2ecf20Sopenharmony_ci int *vptr = va_arg(vargs, int *); 8098c2ecf20Sopenharmony_ci *vptr = data[i]; 8108c2ecf20Sopenharmony_ci } 8118c2ecf20Sopenharmony_ci va_end(vargs); 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci return err; 8148c2ecf20Sopenharmony_ci} 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_cistatic int cx231xx_find_mailbox(struct cx231xx *dev) 8188c2ecf20Sopenharmony_ci{ 8198c2ecf20Sopenharmony_ci u32 signature[4] = { 8208c2ecf20Sopenharmony_ci 0x12345678, 0x34567812, 0x56781234, 0x78123456 8218c2ecf20Sopenharmony_ci }; 8228c2ecf20Sopenharmony_ci int signaturecnt = 0; 8238c2ecf20Sopenharmony_ci u32 value; 8248c2ecf20Sopenharmony_ci int i; 8258c2ecf20Sopenharmony_ci int ret = 0; 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci dprintk(2, "%s()\n", __func__); 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci for (i = 0; i < 0x100; i++) {/*CX231xx_FIRM_IMAGE_SIZE*/ 8308c2ecf20Sopenharmony_ci ret = mc417_memory_read(dev, i, &value); 8318c2ecf20Sopenharmony_ci if (ret < 0) 8328c2ecf20Sopenharmony_ci return ret; 8338c2ecf20Sopenharmony_ci if (value == signature[signaturecnt]) 8348c2ecf20Sopenharmony_ci signaturecnt++; 8358c2ecf20Sopenharmony_ci else 8368c2ecf20Sopenharmony_ci signaturecnt = 0; 8378c2ecf20Sopenharmony_ci if (4 == signaturecnt) { 8388c2ecf20Sopenharmony_ci dprintk(1, "Mailbox signature found at 0x%x\n", i + 1); 8398c2ecf20Sopenharmony_ci return i + 1; 8408c2ecf20Sopenharmony_ci } 8418c2ecf20Sopenharmony_ci } 8428c2ecf20Sopenharmony_ci dprintk(3, "Mailbox signature values not found!\n"); 8438c2ecf20Sopenharmony_ci return -EIO; 8448c2ecf20Sopenharmony_ci} 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_cistatic void mci_write_memory_to_gpio(struct cx231xx *dev, u32 address, u32 value, 8478c2ecf20Sopenharmony_ci u32 *p_fw_image) 8488c2ecf20Sopenharmony_ci{ 8498c2ecf20Sopenharmony_ci u32 temp = 0; 8508c2ecf20Sopenharmony_ci int i = 0; 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_DATA_BYTE0 | ((value & 0x000000FF) << 8); 8538c2ecf20Sopenharmony_ci temp = temp << 10; 8548c2ecf20Sopenharmony_ci *p_fw_image = temp; 8558c2ecf20Sopenharmony_ci p_fw_image++; 8568c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 8578c2ecf20Sopenharmony_ci *p_fw_image = temp; 8588c2ecf20Sopenharmony_ci p_fw_image++; 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci /*write data byte 1;*/ 8618c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_DATA_BYTE1 | (value & 0x0000FF00); 8628c2ecf20Sopenharmony_ci temp = temp << 10; 8638c2ecf20Sopenharmony_ci *p_fw_image = temp; 8648c2ecf20Sopenharmony_ci p_fw_image++; 8658c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 8668c2ecf20Sopenharmony_ci *p_fw_image = temp; 8678c2ecf20Sopenharmony_ci p_fw_image++; 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci /*write data byte 2;*/ 8708c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_DATA_BYTE2 | ((value & 0x00FF0000) >> 8); 8718c2ecf20Sopenharmony_ci temp = temp << 10; 8728c2ecf20Sopenharmony_ci *p_fw_image = temp; 8738c2ecf20Sopenharmony_ci p_fw_image++; 8748c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 8758c2ecf20Sopenharmony_ci *p_fw_image = temp; 8768c2ecf20Sopenharmony_ci p_fw_image++; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci /*write data byte 3;*/ 8798c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_DATA_BYTE3 | ((value & 0xFF000000) >> 16); 8808c2ecf20Sopenharmony_ci temp = temp << 10; 8818c2ecf20Sopenharmony_ci *p_fw_image = temp; 8828c2ecf20Sopenharmony_ci p_fw_image++; 8838c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 8848c2ecf20Sopenharmony_ci *p_fw_image = temp; 8858c2ecf20Sopenharmony_ci p_fw_image++; 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci /* write address byte 2;*/ 8888c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE | 8898c2ecf20Sopenharmony_ci ((address & 0x003F0000) >> 8); 8908c2ecf20Sopenharmony_ci temp = temp << 10; 8918c2ecf20Sopenharmony_ci *p_fw_image = temp; 8928c2ecf20Sopenharmony_ci p_fw_image++; 8938c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 8948c2ecf20Sopenharmony_ci *p_fw_image = temp; 8958c2ecf20Sopenharmony_ci p_fw_image++; 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci /* write address byte 1;*/ 8988c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00); 8998c2ecf20Sopenharmony_ci temp = temp << 10; 9008c2ecf20Sopenharmony_ci *p_fw_image = temp; 9018c2ecf20Sopenharmony_ci p_fw_image++; 9028c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 9038c2ecf20Sopenharmony_ci *p_fw_image = temp; 9048c2ecf20Sopenharmony_ci p_fw_image++; 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci /* write address byte 0;*/ 9078c2ecf20Sopenharmony_ci temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF) << 8); 9088c2ecf20Sopenharmony_ci temp = temp << 10; 9098c2ecf20Sopenharmony_ci *p_fw_image = temp; 9108c2ecf20Sopenharmony_ci p_fw_image++; 9118c2ecf20Sopenharmony_ci temp = temp | (0x05 << 10); 9128c2ecf20Sopenharmony_ci *p_fw_image = temp; 9138c2ecf20Sopenharmony_ci p_fw_image++; 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) { 9168c2ecf20Sopenharmony_ci *p_fw_image = 0xFFFFFFFF; 9178c2ecf20Sopenharmony_ci p_fw_image++; 9188c2ecf20Sopenharmony_ci } 9198c2ecf20Sopenharmony_ci} 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_cistatic int cx231xx_load_firmware(struct cx231xx *dev) 9238c2ecf20Sopenharmony_ci{ 9248c2ecf20Sopenharmony_ci static const unsigned char magic[8] = { 9258c2ecf20Sopenharmony_ci 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa 9268c2ecf20Sopenharmony_ci }; 9278c2ecf20Sopenharmony_ci const struct firmware *firmware; 9288c2ecf20Sopenharmony_ci int i, retval = 0; 9298c2ecf20Sopenharmony_ci u32 value = 0; 9308c2ecf20Sopenharmony_ci u32 gpio_output = 0; 9318c2ecf20Sopenharmony_ci /*u32 checksum = 0;*/ 9328c2ecf20Sopenharmony_ci /*u32 *dataptr;*/ 9338c2ecf20Sopenharmony_ci u32 transfer_size = 0; 9348c2ecf20Sopenharmony_ci u32 fw_data = 0; 9358c2ecf20Sopenharmony_ci u32 address = 0; 9368c2ecf20Sopenharmony_ci /*u32 current_fw[800];*/ 9378c2ecf20Sopenharmony_ci u32 *p_current_fw, *p_fw; 9388c2ecf20Sopenharmony_ci u32 *p_fw_data; 9398c2ecf20Sopenharmony_ci int frame = 0; 9408c2ecf20Sopenharmony_ci u16 _buffer_size = 4096; 9418c2ecf20Sopenharmony_ci u8 *p_buffer; 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci p_current_fw = vmalloc(1884180 * 4); 9448c2ecf20Sopenharmony_ci p_fw = p_current_fw; 9458c2ecf20Sopenharmony_ci if (p_current_fw == NULL) { 9468c2ecf20Sopenharmony_ci dprintk(2, "FAIL!!!\n"); 9478c2ecf20Sopenharmony_ci return -ENOMEM; 9488c2ecf20Sopenharmony_ci } 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci p_buffer = vmalloc(4096); 9518c2ecf20Sopenharmony_ci if (p_buffer == NULL) { 9528c2ecf20Sopenharmony_ci dprintk(2, "FAIL!!!\n"); 9538c2ecf20Sopenharmony_ci vfree(p_current_fw); 9548c2ecf20Sopenharmony_ci return -ENOMEM; 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci dprintk(2, "%s()\n", __func__); 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci /* Save GPIO settings before reset of APU */ 9608c2ecf20Sopenharmony_ci retval |= mc417_memory_read(dev, 0x9020, &gpio_output); 9618c2ecf20Sopenharmony_ci retval |= mc417_memory_read(dev, 0x900C, &value); 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci retval = mc417_register_write(dev, 9648c2ecf20Sopenharmony_ci IVTV_REG_VPU, 0xFFFFFFED); 9658c2ecf20Sopenharmony_ci retval |= mc417_register_write(dev, 9668c2ecf20Sopenharmony_ci IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); 9678c2ecf20Sopenharmony_ci retval |= mc417_register_write(dev, 9688c2ecf20Sopenharmony_ci IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800); 9698c2ecf20Sopenharmony_ci retval |= mc417_register_write(dev, 9708c2ecf20Sopenharmony_ci IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); 9718c2ecf20Sopenharmony_ci retval |= mc417_register_write(dev, 9728c2ecf20Sopenharmony_ci IVTV_REG_APU, 0); 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci if (retval != 0) { 9758c2ecf20Sopenharmony_ci dev_err(dev->dev, 9768c2ecf20Sopenharmony_ci "%s: Error with mc417_register_write\n", __func__); 9778c2ecf20Sopenharmony_ci vfree(p_current_fw); 9788c2ecf20Sopenharmony_ci vfree(p_buffer); 9798c2ecf20Sopenharmony_ci return retval; 9808c2ecf20Sopenharmony_ci } 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci retval = request_firmware(&firmware, CX231xx_FIRM_IMAGE_NAME, 9838c2ecf20Sopenharmony_ci dev->dev); 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci if (retval != 0) { 9868c2ecf20Sopenharmony_ci dev_err(dev->dev, 9878c2ecf20Sopenharmony_ci "ERROR: Hotplug firmware request failed (%s).\n", 9888c2ecf20Sopenharmony_ci CX231xx_FIRM_IMAGE_NAME); 9898c2ecf20Sopenharmony_ci dev_err(dev->dev, 9908c2ecf20Sopenharmony_ci "Please fix your hotplug setup, the board will not work without firmware loaded!\n"); 9918c2ecf20Sopenharmony_ci vfree(p_current_fw); 9928c2ecf20Sopenharmony_ci vfree(p_buffer); 9938c2ecf20Sopenharmony_ci return retval; 9948c2ecf20Sopenharmony_ci } 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) { 9978c2ecf20Sopenharmony_ci dev_err(dev->dev, 9988c2ecf20Sopenharmony_ci "ERROR: Firmware size mismatch (have %zd, expected %d)\n", 9998c2ecf20Sopenharmony_ci firmware->size, CX231xx_FIRM_IMAGE_SIZE); 10008c2ecf20Sopenharmony_ci release_firmware(firmware); 10018c2ecf20Sopenharmony_ci vfree(p_current_fw); 10028c2ecf20Sopenharmony_ci vfree(p_buffer); 10038c2ecf20Sopenharmony_ci return -EINVAL; 10048c2ecf20Sopenharmony_ci } 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci if (0 != memcmp(firmware->data, magic, 8)) { 10078c2ecf20Sopenharmony_ci dev_err(dev->dev, 10088c2ecf20Sopenharmony_ci "ERROR: Firmware magic mismatch, wrong file?\n"); 10098c2ecf20Sopenharmony_ci release_firmware(firmware); 10108c2ecf20Sopenharmony_ci vfree(p_current_fw); 10118c2ecf20Sopenharmony_ci vfree(p_buffer); 10128c2ecf20Sopenharmony_ci return -EINVAL; 10138c2ecf20Sopenharmony_ci } 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci initGPIO(dev); 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci /* transfer to the chip */ 10188c2ecf20Sopenharmony_ci dprintk(2, "Loading firmware to GPIO...\n"); 10198c2ecf20Sopenharmony_ci p_fw_data = (u32 *)firmware->data; 10208c2ecf20Sopenharmony_ci dprintk(2, "firmware->size=%zd\n", firmware->size); 10218c2ecf20Sopenharmony_ci for (transfer_size = 0; transfer_size < firmware->size; 10228c2ecf20Sopenharmony_ci transfer_size += 4) { 10238c2ecf20Sopenharmony_ci fw_data = *p_fw_data; 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci mci_write_memory_to_gpio(dev, address, fw_data, p_current_fw); 10268c2ecf20Sopenharmony_ci address = address + 1; 10278c2ecf20Sopenharmony_ci p_current_fw += 20; 10288c2ecf20Sopenharmony_ci p_fw_data += 1; 10298c2ecf20Sopenharmony_ci } 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci /*download the firmware by ep5-out*/ 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci for (frame = 0; frame < (int)(CX231xx_FIRM_IMAGE_SIZE*20/_buffer_size); 10348c2ecf20Sopenharmony_ci frame++) { 10358c2ecf20Sopenharmony_ci for (i = 0; i < _buffer_size; i++) { 10368c2ecf20Sopenharmony_ci *(p_buffer + i) = (u8)(*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x000000FF); 10378c2ecf20Sopenharmony_ci i++; 10388c2ecf20Sopenharmony_ci *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x0000FF00) >> 8); 10398c2ecf20Sopenharmony_ci i++; 10408c2ecf20Sopenharmony_ci *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x00FF0000) >> 16); 10418c2ecf20Sopenharmony_ci i++; 10428c2ecf20Sopenharmony_ci *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0xFF000000) >> 24); 10438c2ecf20Sopenharmony_ci } 10448c2ecf20Sopenharmony_ci cx231xx_ep5_bulkout(dev, p_buffer, _buffer_size); 10458c2ecf20Sopenharmony_ci } 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci p_current_fw = p_fw; 10488c2ecf20Sopenharmony_ci vfree(p_current_fw); 10498c2ecf20Sopenharmony_ci p_current_fw = NULL; 10508c2ecf20Sopenharmony_ci vfree(p_buffer); 10518c2ecf20Sopenharmony_ci uninitGPIO(dev); 10528c2ecf20Sopenharmony_ci release_firmware(firmware); 10538c2ecf20Sopenharmony_ci dprintk(1, "Firmware upload successful.\n"); 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS, 10568c2ecf20Sopenharmony_ci IVTV_CMD_HW_BLOCKS_RST); 10578c2ecf20Sopenharmony_ci if (retval < 0) { 10588c2ecf20Sopenharmony_ci dev_err(dev->dev, 10598c2ecf20Sopenharmony_ci "%s: Error with mc417_register_write\n", 10608c2ecf20Sopenharmony_ci __func__); 10618c2ecf20Sopenharmony_ci return retval; 10628c2ecf20Sopenharmony_ci } 10638c2ecf20Sopenharmony_ci /* F/W power up disturbs the GPIOs, restore state */ 10648c2ecf20Sopenharmony_ci retval |= mc417_register_write(dev, 0x9020, gpio_output); 10658c2ecf20Sopenharmony_ci retval |= mc417_register_write(dev, 0x900C, value); 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci retval |= mc417_register_read(dev, IVTV_REG_VPU, &value); 10688c2ecf20Sopenharmony_ci retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8); 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci if (retval < 0) { 10718c2ecf20Sopenharmony_ci dev_err(dev->dev, 10728c2ecf20Sopenharmony_ci "%s: Error with mc417_register_write\n", 10738c2ecf20Sopenharmony_ci __func__); 10748c2ecf20Sopenharmony_ci return retval; 10758c2ecf20Sopenharmony_ci } 10768c2ecf20Sopenharmony_ci return 0; 10778c2ecf20Sopenharmony_ci} 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_cistatic void cx231xx_codec_settings(struct cx231xx *dev) 10808c2ecf20Sopenharmony_ci{ 10818c2ecf20Sopenharmony_ci dprintk(1, "%s()\n", __func__); 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci /* assign frame size */ 10848c2ecf20Sopenharmony_ci cx231xx_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, 10858c2ecf20Sopenharmony_ci dev->ts1.height, dev->ts1.width); 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci dev->mpeg_ctrl_handler.width = dev->ts1.width; 10888c2ecf20Sopenharmony_ci dev->mpeg_ctrl_handler.height = dev->ts1.height; 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci cx2341x_handler_setup(&dev->mpeg_ctrl_handler); 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1); 10938c2ecf20Sopenharmony_ci cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1); 10948c2ecf20Sopenharmony_ci} 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_cistatic int cx231xx_initialize_codec(struct cx231xx *dev) 10978c2ecf20Sopenharmony_ci{ 10988c2ecf20Sopenharmony_ci int version; 10998c2ecf20Sopenharmony_ci int retval; 11008c2ecf20Sopenharmony_ci u32 i; 11018c2ecf20Sopenharmony_ci u32 val = 0; 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci dprintk(1, "%s()\n", __func__); 11048c2ecf20Sopenharmony_ci cx231xx_disable656(dev); 11058c2ecf20Sopenharmony_ci retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ 11068c2ecf20Sopenharmony_ci if (retval < 0) { 11078c2ecf20Sopenharmony_ci dprintk(2, "%s: PING OK\n", __func__); 11088c2ecf20Sopenharmony_ci retval = cx231xx_load_firmware(dev); 11098c2ecf20Sopenharmony_ci if (retval < 0) { 11108c2ecf20Sopenharmony_ci dev_err(dev->dev, 11118c2ecf20Sopenharmony_ci "%s: f/w load failed\n", __func__); 11128c2ecf20Sopenharmony_ci return retval; 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci retval = cx231xx_find_mailbox(dev); 11158c2ecf20Sopenharmony_ci if (retval < 0) { 11168c2ecf20Sopenharmony_ci dev_err(dev->dev, "%s: mailbox < 0, error\n", 11178c2ecf20Sopenharmony_ci __func__); 11188c2ecf20Sopenharmony_ci return retval; 11198c2ecf20Sopenharmony_ci } 11208c2ecf20Sopenharmony_ci dev->cx23417_mailbox = retval; 11218c2ecf20Sopenharmony_ci retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); 11228c2ecf20Sopenharmony_ci if (retval < 0) { 11238c2ecf20Sopenharmony_ci dev_err(dev->dev, 11248c2ecf20Sopenharmony_ci "ERROR: cx23417 firmware ping failed!\n"); 11258c2ecf20Sopenharmony_ci return retval; 11268c2ecf20Sopenharmony_ci } 11278c2ecf20Sopenharmony_ci retval = cx231xx_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, 11288c2ecf20Sopenharmony_ci &version); 11298c2ecf20Sopenharmony_ci if (retval < 0) { 11308c2ecf20Sopenharmony_ci dev_err(dev->dev, 11318c2ecf20Sopenharmony_ci "ERROR: cx23417 firmware get encoder: version failed!\n"); 11328c2ecf20Sopenharmony_ci return retval; 11338c2ecf20Sopenharmony_ci } 11348c2ecf20Sopenharmony_ci dprintk(1, "cx23417 firmware version is 0x%08x\n", version); 11358c2ecf20Sopenharmony_ci msleep(200); 11368c2ecf20Sopenharmony_ci } 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci for (i = 0; i < 1; i++) { 11398c2ecf20Sopenharmony_ci retval = mc417_register_read(dev, 0x20f8, &val); 11408c2ecf20Sopenharmony_ci dprintk(3, "***before enable656() VIM Capture Lines = %d ***\n", 11418c2ecf20Sopenharmony_ci val); 11428c2ecf20Sopenharmony_ci if (retval < 0) 11438c2ecf20Sopenharmony_ci return retval; 11448c2ecf20Sopenharmony_ci } 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci cx231xx_enable656(dev); 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci /* stop mpeg capture */ 11498c2ecf20Sopenharmony_ci cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, 1, 3, 4); 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci cx231xx_codec_settings(dev); 11528c2ecf20Sopenharmony_ci msleep(60); 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci/* cx231xx_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0, 11558c2ecf20Sopenharmony_ci CX231xx_FIELD1_SAA7115, CX231xx_FIELD2_SAA7115); 11568c2ecf20Sopenharmony_ci cx231xx_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0, 11578c2ecf20Sopenharmony_ci CX231xx_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11588c2ecf20Sopenharmony_ci 0, 0); 11598c2ecf20Sopenharmony_ci*/ 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci#if 0 11628c2ecf20Sopenharmony_ci /* TODO */ 11638c2ecf20Sopenharmony_ci u32 data[7]; 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci /* Setup to capture VBI */ 11668c2ecf20Sopenharmony_ci data[0] = 0x0001BD00; 11678c2ecf20Sopenharmony_ci data[1] = 1; /* frames per interrupt */ 11688c2ecf20Sopenharmony_ci data[2] = 4; /* total bufs */ 11698c2ecf20Sopenharmony_ci data[3] = 0x91559155; /* start codes */ 11708c2ecf20Sopenharmony_ci data[4] = 0x206080C0; /* stop codes */ 11718c2ecf20Sopenharmony_ci data[5] = 6; /* lines */ 11728c2ecf20Sopenharmony_ci data[6] = 64; /* BPL */ 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1], 11758c2ecf20Sopenharmony_ci data[2], data[3], data[4], data[5], data[6]); 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci for (i = 2; i <= 24; i++) { 11788c2ecf20Sopenharmony_ci int valid; 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci valid = ((i >= 19) && (i <= 21)); 11818c2ecf20Sopenharmony_ci cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i, 11828c2ecf20Sopenharmony_ci valid, 0 , 0, 0); 11838c2ecf20Sopenharmony_ci cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, 11848c2ecf20Sopenharmony_ci i | 0x80000000, valid, 0, 0, 0); 11858c2ecf20Sopenharmony_ci } 11868c2ecf20Sopenharmony_ci#endif 11878c2ecf20Sopenharmony_ci/* cx231xx_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX231xx_UNMUTE); 11888c2ecf20Sopenharmony_ci msleep(60); 11898c2ecf20Sopenharmony_ci*/ 11908c2ecf20Sopenharmony_ci /* initialize the video input */ 11918c2ecf20Sopenharmony_ci retval = cx231xx_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); 11928c2ecf20Sopenharmony_ci if (retval < 0) 11938c2ecf20Sopenharmony_ci return retval; 11948c2ecf20Sopenharmony_ci msleep(60); 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci /* Enable VIP style pixel invalidation so we work with scaled mode */ 11978c2ecf20Sopenharmony_ci mc417_memory_write(dev, 2120, 0x00000080); 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci /* start capturing to the host interface */ 12008c2ecf20Sopenharmony_ci retval = cx231xx_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, 12018c2ecf20Sopenharmony_ci CX231xx_MPEG_CAPTURE, CX231xx_RAW_BITS_NONE); 12028c2ecf20Sopenharmony_ci if (retval < 0) 12038c2ecf20Sopenharmony_ci return retval; 12048c2ecf20Sopenharmony_ci msleep(10); 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci for (i = 0; i < 1; i++) { 12078c2ecf20Sopenharmony_ci mc417_register_read(dev, 0x20f8, &val); 12088c2ecf20Sopenharmony_ci dprintk(3, "***VIM Capture Lines =%d ***\n", val); 12098c2ecf20Sopenharmony_ci } 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci return 0; 12128c2ecf20Sopenharmony_ci} 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------ */ 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_cistatic int queue_setup(struct vb2_queue *vq, 12178c2ecf20Sopenharmony_ci unsigned int *nbuffers, unsigned int *nplanes, 12188c2ecf20Sopenharmony_ci unsigned int sizes[], struct device *alloc_devs[]) 12198c2ecf20Sopenharmony_ci{ 12208c2ecf20Sopenharmony_ci struct cx231xx *dev = vb2_get_drv_priv(vq); 12218c2ecf20Sopenharmony_ci unsigned int size = mpeglinesize * mpeglines; 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci dev->ts1.ts_packet_size = mpeglinesize; 12248c2ecf20Sopenharmony_ci dev->ts1.ts_packet_count = mpeglines; 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci if (vq->num_buffers + *nbuffers < CX231XX_MIN_BUF) 12278c2ecf20Sopenharmony_ci *nbuffers = CX231XX_MIN_BUF - vq->num_buffers; 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci if (*nplanes) 12308c2ecf20Sopenharmony_ci return sizes[0] < size ? -EINVAL : 0; 12318c2ecf20Sopenharmony_ci *nplanes = 1; 12328c2ecf20Sopenharmony_ci sizes[0] = mpeglinesize * mpeglines; 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci return 0; 12358c2ecf20Sopenharmony_ci} 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_cistatic void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *urb, 12388c2ecf20Sopenharmony_ci struct cx231xx_dmaqueue *dma_q) 12398c2ecf20Sopenharmony_ci{ 12408c2ecf20Sopenharmony_ci void *vbuf; 12418c2ecf20Sopenharmony_ci struct cx231xx_buffer *buf; 12428c2ecf20Sopenharmony_ci u32 tail_data = 0; 12438c2ecf20Sopenharmony_ci char *p_data; 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci if (dma_q->mpeg_buffer_done == 0) { 12468c2ecf20Sopenharmony_ci if (list_empty(&dma_q->active)) 12478c2ecf20Sopenharmony_ci return; 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci buf = list_entry(dma_q->active.next, 12508c2ecf20Sopenharmony_ci struct cx231xx_buffer, list); 12518c2ecf20Sopenharmony_ci dev->video_mode.isoc_ctl.buf = buf; 12528c2ecf20Sopenharmony_ci dma_q->mpeg_buffer_done = 1; 12538c2ecf20Sopenharmony_ci } 12548c2ecf20Sopenharmony_ci /* Fill buffer */ 12558c2ecf20Sopenharmony_ci buf = dev->video_mode.isoc_ctl.buf; 12568c2ecf20Sopenharmony_ci vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci if ((dma_q->mpeg_buffer_completed+len) < 12598c2ecf20Sopenharmony_ci mpeglines*mpeglinesize) { 12608c2ecf20Sopenharmony_ci if (dma_q->add_ps_package_head == 12618c2ecf20Sopenharmony_ci CX231XX_NEED_ADD_PS_PACKAGE_HEAD) { 12628c2ecf20Sopenharmony_ci memcpy(vbuf+dma_q->mpeg_buffer_completed, 12638c2ecf20Sopenharmony_ci dma_q->ps_head, 3); 12648c2ecf20Sopenharmony_ci dma_q->mpeg_buffer_completed = 12658c2ecf20Sopenharmony_ci dma_q->mpeg_buffer_completed + 3; 12668c2ecf20Sopenharmony_ci dma_q->add_ps_package_head = 12678c2ecf20Sopenharmony_ci CX231XX_NONEED_PS_PACKAGE_HEAD; 12688c2ecf20Sopenharmony_ci } 12698c2ecf20Sopenharmony_ci memcpy(vbuf+dma_q->mpeg_buffer_completed, data, len); 12708c2ecf20Sopenharmony_ci dma_q->mpeg_buffer_completed = 12718c2ecf20Sopenharmony_ci dma_q->mpeg_buffer_completed + len; 12728c2ecf20Sopenharmony_ci } else { 12738c2ecf20Sopenharmony_ci dma_q->mpeg_buffer_done = 0; 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci tail_data = 12768c2ecf20Sopenharmony_ci mpeglines*mpeglinesize - dma_q->mpeg_buffer_completed; 12778c2ecf20Sopenharmony_ci memcpy(vbuf+dma_q->mpeg_buffer_completed, 12788c2ecf20Sopenharmony_ci data, tail_data); 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci buf->vb.vb2_buf.timestamp = ktime_get_ns(); 12818c2ecf20Sopenharmony_ci buf->vb.sequence = dma_q->sequence++; 12828c2ecf20Sopenharmony_ci list_del(&buf->list); 12838c2ecf20Sopenharmony_ci vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); 12848c2ecf20Sopenharmony_ci dma_q->mpeg_buffer_completed = 0; 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci if (len - tail_data > 0) { 12878c2ecf20Sopenharmony_ci p_data = data + tail_data; 12888c2ecf20Sopenharmony_ci dma_q->left_data_count = len - tail_data; 12898c2ecf20Sopenharmony_ci memcpy(dma_q->p_left_data, 12908c2ecf20Sopenharmony_ci p_data, len - tail_data); 12918c2ecf20Sopenharmony_ci } 12928c2ecf20Sopenharmony_ci } 12938c2ecf20Sopenharmony_ci} 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_cistatic void buffer_filled(char *data, int len, struct urb *urb, 12968c2ecf20Sopenharmony_ci struct cx231xx_dmaqueue *dma_q) 12978c2ecf20Sopenharmony_ci{ 12988c2ecf20Sopenharmony_ci void *vbuf; 12998c2ecf20Sopenharmony_ci struct cx231xx_buffer *buf; 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci if (list_empty(&dma_q->active)) 13028c2ecf20Sopenharmony_ci return; 13038c2ecf20Sopenharmony_ci 13048c2ecf20Sopenharmony_ci buf = list_entry(dma_q->active.next, struct cx231xx_buffer, list); 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci /* Fill buffer */ 13078c2ecf20Sopenharmony_ci vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); 13088c2ecf20Sopenharmony_ci memcpy(vbuf, data, len); 13098c2ecf20Sopenharmony_ci buf->vb.sequence = dma_q->sequence++; 13108c2ecf20Sopenharmony_ci buf->vb.vb2_buf.timestamp = ktime_get_ns(); 13118c2ecf20Sopenharmony_ci list_del(&buf->list); 13128c2ecf20Sopenharmony_ci vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); 13138c2ecf20Sopenharmony_ci} 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_cistatic int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) 13168c2ecf20Sopenharmony_ci{ 13178c2ecf20Sopenharmony_ci struct cx231xx_dmaqueue *dma_q = urb->context; 13188c2ecf20Sopenharmony_ci unsigned char *p_buffer; 13198c2ecf20Sopenharmony_ci u32 buffer_size = 0; 13208c2ecf20Sopenharmony_ci u32 i = 0; 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci for (i = 0; i < urb->number_of_packets; i++) { 13238c2ecf20Sopenharmony_ci if (dma_q->left_data_count > 0) { 13248c2ecf20Sopenharmony_ci buffer_copy(dev, dma_q->p_left_data, 13258c2ecf20Sopenharmony_ci dma_q->left_data_count, urb, dma_q); 13268c2ecf20Sopenharmony_ci dma_q->mpeg_buffer_completed = dma_q->left_data_count; 13278c2ecf20Sopenharmony_ci dma_q->left_data_count = 0; 13288c2ecf20Sopenharmony_ci } 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci p_buffer = urb->transfer_buffer + 13318c2ecf20Sopenharmony_ci urb->iso_frame_desc[i].offset; 13328c2ecf20Sopenharmony_ci buffer_size = urb->iso_frame_desc[i].actual_length; 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_ci if (buffer_size > 0) 13358c2ecf20Sopenharmony_ci buffer_copy(dev, p_buffer, buffer_size, urb, dma_q); 13368c2ecf20Sopenharmony_ci } 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_ci return 0; 13398c2ecf20Sopenharmony_ci} 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_cistatic int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb) 13428c2ecf20Sopenharmony_ci{ 13438c2ecf20Sopenharmony_ci struct cx231xx_dmaqueue *dma_q = urb->context; 13448c2ecf20Sopenharmony_ci unsigned char *p_buffer, *buffer; 13458c2ecf20Sopenharmony_ci u32 buffer_size = 0; 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci p_buffer = urb->transfer_buffer; 13488c2ecf20Sopenharmony_ci buffer_size = urb->actual_length; 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci buffer = kmalloc(buffer_size, GFP_ATOMIC); 13518c2ecf20Sopenharmony_ci if (!buffer) 13528c2ecf20Sopenharmony_ci return -ENOMEM; 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci memcpy(buffer, dma_q->ps_head, 3); 13558c2ecf20Sopenharmony_ci memcpy(buffer+3, p_buffer, buffer_size-3); 13568c2ecf20Sopenharmony_ci memcpy(dma_q->ps_head, p_buffer+buffer_size-3, 3); 13578c2ecf20Sopenharmony_ci 13588c2ecf20Sopenharmony_ci p_buffer = buffer; 13598c2ecf20Sopenharmony_ci buffer_filled(p_buffer, buffer_size, urb, dma_q); 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_ci kfree(buffer); 13628c2ecf20Sopenharmony_ci return 0; 13638c2ecf20Sopenharmony_ci} 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_cistatic void buffer_queue(struct vb2_buffer *vb) 13668c2ecf20Sopenharmony_ci{ 13678c2ecf20Sopenharmony_ci struct cx231xx_buffer *buf = 13688c2ecf20Sopenharmony_ci container_of(vb, struct cx231xx_buffer, vb.vb2_buf); 13698c2ecf20Sopenharmony_ci struct cx231xx *dev = vb2_get_drv_priv(vb->vb2_queue); 13708c2ecf20Sopenharmony_ci struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; 13718c2ecf20Sopenharmony_ci unsigned long flags; 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev->video_mode.slock, flags); 13748c2ecf20Sopenharmony_ci list_add_tail(&buf->list, &vidq->active); 13758c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->video_mode.slock, flags); 13768c2ecf20Sopenharmony_ci} 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_cistatic void return_all_buffers(struct cx231xx *dev, 13798c2ecf20Sopenharmony_ci enum vb2_buffer_state state) 13808c2ecf20Sopenharmony_ci{ 13818c2ecf20Sopenharmony_ci struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; 13828c2ecf20Sopenharmony_ci struct cx231xx_buffer *buf, *node; 13838c2ecf20Sopenharmony_ci unsigned long flags; 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev->video_mode.slock, flags); 13868c2ecf20Sopenharmony_ci list_for_each_entry_safe(buf, node, &vidq->active, list) { 13878c2ecf20Sopenharmony_ci vb2_buffer_done(&buf->vb.vb2_buf, state); 13888c2ecf20Sopenharmony_ci list_del(&buf->list); 13898c2ecf20Sopenharmony_ci } 13908c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->video_mode.slock, flags); 13918c2ecf20Sopenharmony_ci} 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_cistatic int start_streaming(struct vb2_queue *vq, unsigned int count) 13948c2ecf20Sopenharmony_ci{ 13958c2ecf20Sopenharmony_ci struct cx231xx *dev = vb2_get_drv_priv(vq); 13968c2ecf20Sopenharmony_ci struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; 13978c2ecf20Sopenharmony_ci int ret = 0; 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci vidq->sequence = 0; 14008c2ecf20Sopenharmony_ci dev->mode_tv = 1; 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci cx231xx_set_alt_setting(dev, INDEX_VANC, 1); 14038c2ecf20Sopenharmony_ci cx231xx_set_gpio_value(dev, 2, 0); 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_ci cx231xx_initialize_codec(dev); 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci cx231xx_start_TS1(dev); 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci cx231xx_set_alt_setting(dev, INDEX_TS1, 0); 14108c2ecf20Sopenharmony_ci cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); 14118c2ecf20Sopenharmony_ci if (dev->USE_ISO) 14128c2ecf20Sopenharmony_ci ret = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, 14138c2ecf20Sopenharmony_ci CX231XX_NUM_BUFS, 14148c2ecf20Sopenharmony_ci dev->ts1_mode.max_pkt_size, 14158c2ecf20Sopenharmony_ci cx231xx_isoc_copy); 14168c2ecf20Sopenharmony_ci else 14178c2ecf20Sopenharmony_ci ret = cx231xx_init_bulk(dev, 320, 5, 14188c2ecf20Sopenharmony_ci dev->ts1_mode.max_pkt_size, 14198c2ecf20Sopenharmony_ci cx231xx_bulk_copy); 14208c2ecf20Sopenharmony_ci if (ret) 14218c2ecf20Sopenharmony_ci return_all_buffers(dev, VB2_BUF_STATE_QUEUED); 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci call_all(dev, video, s_stream, 1); 14248c2ecf20Sopenharmony_ci return ret; 14258c2ecf20Sopenharmony_ci} 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_cistatic void stop_streaming(struct vb2_queue *vq) 14288c2ecf20Sopenharmony_ci{ 14298c2ecf20Sopenharmony_ci struct cx231xx *dev = vb2_get_drv_priv(vq); 14308c2ecf20Sopenharmony_ci unsigned long flags; 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_ci call_all(dev, video, s_stream, 0); 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci cx231xx_stop_TS1(dev); 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci /* do this before setting alternate! */ 14378c2ecf20Sopenharmony_ci if (dev->USE_ISO) 14388c2ecf20Sopenharmony_ci cx231xx_uninit_isoc(dev); 14398c2ecf20Sopenharmony_ci else 14408c2ecf20Sopenharmony_ci cx231xx_uninit_bulk(dev); 14418c2ecf20Sopenharmony_ci cx231xx_set_mode(dev, CX231XX_SUSPEND); 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, 14448c2ecf20Sopenharmony_ci CX231xx_END_NOW, CX231xx_MPEG_CAPTURE, 14458c2ecf20Sopenharmony_ci CX231xx_RAW_BITS_NONE); 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev->video_mode.slock, flags); 14488c2ecf20Sopenharmony_ci if (dev->USE_ISO) 14498c2ecf20Sopenharmony_ci dev->video_mode.isoc_ctl.buf = NULL; 14508c2ecf20Sopenharmony_ci else 14518c2ecf20Sopenharmony_ci dev->video_mode.bulk_ctl.buf = NULL; 14528c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->video_mode.slock, flags); 14538c2ecf20Sopenharmony_ci return_all_buffers(dev, VB2_BUF_STATE_ERROR); 14548c2ecf20Sopenharmony_ci} 14558c2ecf20Sopenharmony_ci 14568c2ecf20Sopenharmony_cistatic struct vb2_ops cx231xx_video_qops = { 14578c2ecf20Sopenharmony_ci .queue_setup = queue_setup, 14588c2ecf20Sopenharmony_ci .buf_queue = buffer_queue, 14598c2ecf20Sopenharmony_ci .start_streaming = start_streaming, 14608c2ecf20Sopenharmony_ci .stop_streaming = stop_streaming, 14618c2ecf20Sopenharmony_ci .wait_prepare = vb2_ops_wait_prepare, 14628c2ecf20Sopenharmony_ci .wait_finish = vb2_ops_wait_finish, 14638c2ecf20Sopenharmony_ci}; 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------ */ 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_cistatic int vidioc_g_pixelaspect(struct file *file, void *priv, 14688c2ecf20Sopenharmony_ci int type, struct v4l2_fract *f) 14698c2ecf20Sopenharmony_ci{ 14708c2ecf20Sopenharmony_ci struct cx231xx *dev = video_drvdata(file); 14718c2ecf20Sopenharmony_ci bool is_50hz = dev->encodernorm.id & V4L2_STD_625_50; 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 14748c2ecf20Sopenharmony_ci return -EINVAL; 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci f->numerator = is_50hz ? 54 : 11; 14778c2ecf20Sopenharmony_ci f->denominator = is_50hz ? 59 : 10; 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci return 0; 14808c2ecf20Sopenharmony_ci} 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_cistatic int vidioc_g_selection(struct file *file, void *priv, 14838c2ecf20Sopenharmony_ci struct v4l2_selection *s) 14848c2ecf20Sopenharmony_ci{ 14858c2ecf20Sopenharmony_ci struct cx231xx *dev = video_drvdata(file); 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_ci if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 14888c2ecf20Sopenharmony_ci return -EINVAL; 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci switch (s->target) { 14918c2ecf20Sopenharmony_ci case V4L2_SEL_TGT_CROP_BOUNDS: 14928c2ecf20Sopenharmony_ci case V4L2_SEL_TGT_CROP_DEFAULT: 14938c2ecf20Sopenharmony_ci s->r.left = 0; 14948c2ecf20Sopenharmony_ci s->r.top = 0; 14958c2ecf20Sopenharmony_ci s->r.width = dev->ts1.width; 14968c2ecf20Sopenharmony_ci s->r.height = dev->ts1.height; 14978c2ecf20Sopenharmony_ci break; 14988c2ecf20Sopenharmony_ci default: 14998c2ecf20Sopenharmony_ci return -EINVAL; 15008c2ecf20Sopenharmony_ci } 15018c2ecf20Sopenharmony_ci return 0; 15028c2ecf20Sopenharmony_ci} 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_cistatic int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm) 15058c2ecf20Sopenharmony_ci{ 15068c2ecf20Sopenharmony_ci struct cx231xx *dev = video_drvdata(file); 15078c2ecf20Sopenharmony_ci 15088c2ecf20Sopenharmony_ci *norm = dev->encodernorm.id; 15098c2ecf20Sopenharmony_ci return 0; 15108c2ecf20Sopenharmony_ci} 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_cistatic int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) 15138c2ecf20Sopenharmony_ci{ 15148c2ecf20Sopenharmony_ci struct cx231xx *dev = video_drvdata(file); 15158c2ecf20Sopenharmony_ci unsigned int i; 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(cx231xx_tvnorms); i++) 15188c2ecf20Sopenharmony_ci if (id & cx231xx_tvnorms[i].id) 15198c2ecf20Sopenharmony_ci break; 15208c2ecf20Sopenharmony_ci if (i == ARRAY_SIZE(cx231xx_tvnorms)) 15218c2ecf20Sopenharmony_ci return -EINVAL; 15228c2ecf20Sopenharmony_ci dev->encodernorm = cx231xx_tvnorms[i]; 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci if (dev->encodernorm.id & 0xb000) { 15258c2ecf20Sopenharmony_ci dprintk(3, "encodernorm set to NTSC\n"); 15268c2ecf20Sopenharmony_ci dev->norm = V4L2_STD_NTSC; 15278c2ecf20Sopenharmony_ci dev->ts1.height = 480; 15288c2ecf20Sopenharmony_ci cx2341x_handler_set_50hz(&dev->mpeg_ctrl_handler, false); 15298c2ecf20Sopenharmony_ci } else { 15308c2ecf20Sopenharmony_ci dprintk(3, "encodernorm set to PAL\n"); 15318c2ecf20Sopenharmony_ci dev->norm = V4L2_STD_PAL_B; 15328c2ecf20Sopenharmony_ci dev->ts1.height = 576; 15338c2ecf20Sopenharmony_ci cx2341x_handler_set_50hz(&dev->mpeg_ctrl_handler, true); 15348c2ecf20Sopenharmony_ci } 15358c2ecf20Sopenharmony_ci call_all(dev, video, s_std, dev->norm); 15368c2ecf20Sopenharmony_ci /* do mode control overrides */ 15378c2ecf20Sopenharmony_ci cx231xx_do_mode_ctrl_overrides(dev); 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci dprintk(3, "exit vidioc_s_std() i=0x%x\n", i); 15408c2ecf20Sopenharmony_ci return 0; 15418c2ecf20Sopenharmony_ci} 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_cistatic int vidioc_s_ctrl(struct file *file, void *priv, 15448c2ecf20Sopenharmony_ci struct v4l2_control *ctl) 15458c2ecf20Sopenharmony_ci{ 15468c2ecf20Sopenharmony_ci struct cx231xx *dev = video_drvdata(file); 15478c2ecf20Sopenharmony_ci struct v4l2_subdev *sd; 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci dprintk(3, "enter vidioc_s_ctrl()\n"); 15508c2ecf20Sopenharmony_ci /* Update the A/V core */ 15518c2ecf20Sopenharmony_ci v4l2_device_for_each_subdev(sd, &dev->v4l2_dev) 15528c2ecf20Sopenharmony_ci v4l2_s_ctrl(NULL, sd->ctrl_handler, ctl); 15538c2ecf20Sopenharmony_ci dprintk(3, "exit vidioc_s_ctrl()\n"); 15548c2ecf20Sopenharmony_ci return 0; 15558c2ecf20Sopenharmony_ci} 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_cistatic int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, 15588c2ecf20Sopenharmony_ci struct v4l2_fmtdesc *f) 15598c2ecf20Sopenharmony_ci{ 15608c2ecf20Sopenharmony_ci if (f->index != 0) 15618c2ecf20Sopenharmony_ci return -EINVAL; 15628c2ecf20Sopenharmony_ci 15638c2ecf20Sopenharmony_ci f->pixelformat = V4L2_PIX_FMT_MPEG; 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ci return 0; 15668c2ecf20Sopenharmony_ci} 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_cistatic int vidioc_g_fmt_vid_cap(struct file *file, void *priv, 15698c2ecf20Sopenharmony_ci struct v4l2_format *f) 15708c2ecf20Sopenharmony_ci{ 15718c2ecf20Sopenharmony_ci struct cx231xx *dev = video_drvdata(file); 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_ci dprintk(3, "enter vidioc_g_fmt_vid_cap()\n"); 15748c2ecf20Sopenharmony_ci f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; 15758c2ecf20Sopenharmony_ci f->fmt.pix.bytesperline = 0; 15768c2ecf20Sopenharmony_ci f->fmt.pix.sizeimage = mpeglines * mpeglinesize; 15778c2ecf20Sopenharmony_ci f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; 15788c2ecf20Sopenharmony_ci f->fmt.pix.width = dev->ts1.width; 15798c2ecf20Sopenharmony_ci f->fmt.pix.height = dev->ts1.height; 15808c2ecf20Sopenharmony_ci f->fmt.pix.field = V4L2_FIELD_INTERLACED; 15818c2ecf20Sopenharmony_ci dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d\n", 15828c2ecf20Sopenharmony_ci dev->ts1.width, dev->ts1.height); 15838c2ecf20Sopenharmony_ci dprintk(3, "exit vidioc_g_fmt_vid_cap()\n"); 15848c2ecf20Sopenharmony_ci return 0; 15858c2ecf20Sopenharmony_ci} 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_cistatic int vidioc_try_fmt_vid_cap(struct file *file, void *priv, 15888c2ecf20Sopenharmony_ci struct v4l2_format *f) 15898c2ecf20Sopenharmony_ci{ 15908c2ecf20Sopenharmony_ci struct cx231xx *dev = video_drvdata(file); 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_ci dprintk(3, "enter vidioc_try_fmt_vid_cap()\n"); 15938c2ecf20Sopenharmony_ci f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; 15948c2ecf20Sopenharmony_ci f->fmt.pix.bytesperline = 0; 15958c2ecf20Sopenharmony_ci f->fmt.pix.sizeimage = mpeglines * mpeglinesize; 15968c2ecf20Sopenharmony_ci f->fmt.pix.field = V4L2_FIELD_INTERLACED; 15978c2ecf20Sopenharmony_ci f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; 15988c2ecf20Sopenharmony_ci dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d\n", 15998c2ecf20Sopenharmony_ci dev->ts1.width, dev->ts1.height); 16008c2ecf20Sopenharmony_ci dprintk(3, "exit vidioc_try_fmt_vid_cap()\n"); 16018c2ecf20Sopenharmony_ci return 0; 16028c2ecf20Sopenharmony_ci} 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_cistatic int vidioc_log_status(struct file *file, void *priv) 16058c2ecf20Sopenharmony_ci{ 16068c2ecf20Sopenharmony_ci struct cx231xx *dev = video_drvdata(file); 16078c2ecf20Sopenharmony_ci 16088c2ecf20Sopenharmony_ci call_all(dev, core, log_status); 16098c2ecf20Sopenharmony_ci return v4l2_ctrl_log_status(file, priv); 16108c2ecf20Sopenharmony_ci} 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_cistatic const struct v4l2_file_operations mpeg_fops = { 16138c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 16148c2ecf20Sopenharmony_ci .open = v4l2_fh_open, 16158c2ecf20Sopenharmony_ci .release = vb2_fop_release, 16168c2ecf20Sopenharmony_ci .read = vb2_fop_read, 16178c2ecf20Sopenharmony_ci .poll = vb2_fop_poll, 16188c2ecf20Sopenharmony_ci .mmap = vb2_fop_mmap, 16198c2ecf20Sopenharmony_ci .unlocked_ioctl = video_ioctl2, 16208c2ecf20Sopenharmony_ci}; 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_cistatic const struct v4l2_ioctl_ops mpeg_ioctl_ops = { 16238c2ecf20Sopenharmony_ci .vidioc_s_std = vidioc_s_std, 16248c2ecf20Sopenharmony_ci .vidioc_g_std = vidioc_g_std, 16258c2ecf20Sopenharmony_ci .vidioc_g_tuner = cx231xx_g_tuner, 16268c2ecf20Sopenharmony_ci .vidioc_s_tuner = cx231xx_s_tuner, 16278c2ecf20Sopenharmony_ci .vidioc_g_frequency = cx231xx_g_frequency, 16288c2ecf20Sopenharmony_ci .vidioc_s_frequency = cx231xx_s_frequency, 16298c2ecf20Sopenharmony_ci .vidioc_enum_input = cx231xx_enum_input, 16308c2ecf20Sopenharmony_ci .vidioc_g_input = cx231xx_g_input, 16318c2ecf20Sopenharmony_ci .vidioc_s_input = cx231xx_s_input, 16328c2ecf20Sopenharmony_ci .vidioc_s_ctrl = vidioc_s_ctrl, 16338c2ecf20Sopenharmony_ci .vidioc_g_pixelaspect = vidioc_g_pixelaspect, 16348c2ecf20Sopenharmony_ci .vidioc_g_selection = vidioc_g_selection, 16358c2ecf20Sopenharmony_ci .vidioc_querycap = cx231xx_querycap, 16368c2ecf20Sopenharmony_ci .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, 16378c2ecf20Sopenharmony_ci .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, 16388c2ecf20Sopenharmony_ci .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, 16398c2ecf20Sopenharmony_ci .vidioc_s_fmt_vid_cap = vidioc_try_fmt_vid_cap, 16408c2ecf20Sopenharmony_ci .vidioc_reqbufs = vb2_ioctl_reqbufs, 16418c2ecf20Sopenharmony_ci .vidioc_querybuf = vb2_ioctl_querybuf, 16428c2ecf20Sopenharmony_ci .vidioc_qbuf = vb2_ioctl_qbuf, 16438c2ecf20Sopenharmony_ci .vidioc_dqbuf = vb2_ioctl_dqbuf, 16448c2ecf20Sopenharmony_ci .vidioc_streamon = vb2_ioctl_streamon, 16458c2ecf20Sopenharmony_ci .vidioc_streamoff = vb2_ioctl_streamoff, 16468c2ecf20Sopenharmony_ci .vidioc_log_status = vidioc_log_status, 16478c2ecf20Sopenharmony_ci#ifdef CONFIG_VIDEO_ADV_DEBUG 16488c2ecf20Sopenharmony_ci .vidioc_g_register = cx231xx_g_register, 16498c2ecf20Sopenharmony_ci .vidioc_s_register = cx231xx_s_register, 16508c2ecf20Sopenharmony_ci#endif 16518c2ecf20Sopenharmony_ci .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 16528c2ecf20Sopenharmony_ci .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 16538c2ecf20Sopenharmony_ci}; 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_cistatic struct video_device cx231xx_mpeg_template = { 16568c2ecf20Sopenharmony_ci .name = "cx231xx", 16578c2ecf20Sopenharmony_ci .fops = &mpeg_fops, 16588c2ecf20Sopenharmony_ci .ioctl_ops = &mpeg_ioctl_ops, 16598c2ecf20Sopenharmony_ci .minor = -1, 16608c2ecf20Sopenharmony_ci .tvnorms = V4L2_STD_ALL, 16618c2ecf20Sopenharmony_ci}; 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_civoid cx231xx_417_unregister(struct cx231xx *dev) 16648c2ecf20Sopenharmony_ci{ 16658c2ecf20Sopenharmony_ci dprintk(1, "%s()\n", __func__); 16668c2ecf20Sopenharmony_ci dprintk(3, "%s()\n", __func__); 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci if (video_is_registered(&dev->v4l_device)) { 16698c2ecf20Sopenharmony_ci video_unregister_device(&dev->v4l_device); 16708c2ecf20Sopenharmony_ci v4l2_ctrl_handler_free(&dev->mpeg_ctrl_handler.hdl); 16718c2ecf20Sopenharmony_ci } 16728c2ecf20Sopenharmony_ci} 16738c2ecf20Sopenharmony_ci 16748c2ecf20Sopenharmony_cistatic int cx231xx_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val) 16758c2ecf20Sopenharmony_ci{ 16768c2ecf20Sopenharmony_ci struct cx231xx *dev = container_of(cxhdl, struct cx231xx, mpeg_ctrl_handler); 16778c2ecf20Sopenharmony_ci int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; 16788c2ecf20Sopenharmony_ci struct v4l2_subdev_format format = { 16798c2ecf20Sopenharmony_ci .which = V4L2_SUBDEV_FORMAT_ACTIVE, 16808c2ecf20Sopenharmony_ci }; 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci /* fix videodecoder resolution */ 16838c2ecf20Sopenharmony_ci format.format.width = cxhdl->width / (is_mpeg1 ? 2 : 1); 16848c2ecf20Sopenharmony_ci format.format.height = cxhdl->height; 16858c2ecf20Sopenharmony_ci format.format.code = MEDIA_BUS_FMT_FIXED; 16868c2ecf20Sopenharmony_ci v4l2_subdev_call(dev->sd_cx25840, pad, set_fmt, NULL, &format); 16878c2ecf20Sopenharmony_ci return 0; 16888c2ecf20Sopenharmony_ci} 16898c2ecf20Sopenharmony_ci 16908c2ecf20Sopenharmony_cistatic int cx231xx_s_audio_sampling_freq(struct cx2341x_handler *cxhdl, u32 idx) 16918c2ecf20Sopenharmony_ci{ 16928c2ecf20Sopenharmony_ci static const u32 freqs[3] = { 44100, 48000, 32000 }; 16938c2ecf20Sopenharmony_ci struct cx231xx *dev = container_of(cxhdl, struct cx231xx, mpeg_ctrl_handler); 16948c2ecf20Sopenharmony_ci 16958c2ecf20Sopenharmony_ci /* The audio clock of the digitizer must match the codec sample 16968c2ecf20Sopenharmony_ci rate otherwise you get some very strange effects. */ 16978c2ecf20Sopenharmony_ci if (idx < ARRAY_SIZE(freqs)) 16988c2ecf20Sopenharmony_ci call_all(dev, audio, s_clock_freq, freqs[idx]); 16998c2ecf20Sopenharmony_ci return 0; 17008c2ecf20Sopenharmony_ci} 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_cistatic const struct cx2341x_handler_ops cx231xx_ops = { 17038c2ecf20Sopenharmony_ci /* needed for the video clock freq */ 17048c2ecf20Sopenharmony_ci .s_audio_sampling_freq = cx231xx_s_audio_sampling_freq, 17058c2ecf20Sopenharmony_ci /* needed for setting up the video resolution */ 17068c2ecf20Sopenharmony_ci .s_video_encoding = cx231xx_s_video_encoding, 17078c2ecf20Sopenharmony_ci}; 17088c2ecf20Sopenharmony_ci 17098c2ecf20Sopenharmony_cistatic void cx231xx_video_dev_init( 17108c2ecf20Sopenharmony_ci struct cx231xx *dev, 17118c2ecf20Sopenharmony_ci struct usb_device *usbdev, 17128c2ecf20Sopenharmony_ci struct video_device *vfd, 17138c2ecf20Sopenharmony_ci const struct video_device *template, 17148c2ecf20Sopenharmony_ci const char *type) 17158c2ecf20Sopenharmony_ci{ 17168c2ecf20Sopenharmony_ci dprintk(1, "%s()\n", __func__); 17178c2ecf20Sopenharmony_ci *vfd = *template; 17188c2ecf20Sopenharmony_ci snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, 17198c2ecf20Sopenharmony_ci type, cx231xx_boards[dev->model].name); 17208c2ecf20Sopenharmony_ci 17218c2ecf20Sopenharmony_ci vfd->v4l2_dev = &dev->v4l2_dev; 17228c2ecf20Sopenharmony_ci vfd->lock = &dev->lock; 17238c2ecf20Sopenharmony_ci vfd->release = video_device_release_empty; 17248c2ecf20Sopenharmony_ci vfd->ctrl_handler = &dev->mpeg_ctrl_handler.hdl; 17258c2ecf20Sopenharmony_ci video_set_drvdata(vfd, dev); 17268c2ecf20Sopenharmony_ci if (dev->tuner_type == TUNER_ABSENT) { 17278c2ecf20Sopenharmony_ci v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY); 17288c2ecf20Sopenharmony_ci v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY); 17298c2ecf20Sopenharmony_ci v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER); 17308c2ecf20Sopenharmony_ci v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER); 17318c2ecf20Sopenharmony_ci } 17328c2ecf20Sopenharmony_ci} 17338c2ecf20Sopenharmony_ci 17348c2ecf20Sopenharmony_ciint cx231xx_417_register(struct cx231xx *dev) 17358c2ecf20Sopenharmony_ci{ 17368c2ecf20Sopenharmony_ci /* FIXME: Port1 hardcoded here */ 17378c2ecf20Sopenharmony_ci int err; 17388c2ecf20Sopenharmony_ci struct cx231xx_tsport *tsport = &dev->ts1; 17398c2ecf20Sopenharmony_ci struct vb2_queue *q; 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci dprintk(1, "%s()\n", __func__); 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci /* Set default TV standard */ 17448c2ecf20Sopenharmony_ci dev->encodernorm = cx231xx_tvnorms[0]; 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci if (dev->encodernorm.id & V4L2_STD_525_60) 17478c2ecf20Sopenharmony_ci tsport->height = 480; 17488c2ecf20Sopenharmony_ci else 17498c2ecf20Sopenharmony_ci tsport->height = 576; 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_ci tsport->width = 720; 17528c2ecf20Sopenharmony_ci err = cx2341x_handler_init(&dev->mpeg_ctrl_handler, 50); 17538c2ecf20Sopenharmony_ci if (err) { 17548c2ecf20Sopenharmony_ci dprintk(3, "%s: can't init cx2341x controls\n", dev->name); 17558c2ecf20Sopenharmony_ci return err; 17568c2ecf20Sopenharmony_ci } 17578c2ecf20Sopenharmony_ci dev->mpeg_ctrl_handler.func = cx231xx_mbox_func; 17588c2ecf20Sopenharmony_ci dev->mpeg_ctrl_handler.priv = dev; 17598c2ecf20Sopenharmony_ci dev->mpeg_ctrl_handler.ops = &cx231xx_ops; 17608c2ecf20Sopenharmony_ci if (dev->sd_cx25840) 17618c2ecf20Sopenharmony_ci v4l2_ctrl_add_handler(&dev->mpeg_ctrl_handler.hdl, 17628c2ecf20Sopenharmony_ci dev->sd_cx25840->ctrl_handler, NULL, false); 17638c2ecf20Sopenharmony_ci if (dev->mpeg_ctrl_handler.hdl.error) { 17648c2ecf20Sopenharmony_ci err = dev->mpeg_ctrl_handler.hdl.error; 17658c2ecf20Sopenharmony_ci dprintk(3, "%s: can't add cx25840 controls\n", dev->name); 17668c2ecf20Sopenharmony_ci v4l2_ctrl_handler_free(&dev->mpeg_ctrl_handler.hdl); 17678c2ecf20Sopenharmony_ci return err; 17688c2ecf20Sopenharmony_ci } 17698c2ecf20Sopenharmony_ci dev->norm = V4L2_STD_NTSC; 17708c2ecf20Sopenharmony_ci 17718c2ecf20Sopenharmony_ci dev->mpeg_ctrl_handler.port = CX2341X_PORT_SERIAL; 17728c2ecf20Sopenharmony_ci cx2341x_handler_set_50hz(&dev->mpeg_ctrl_handler, false); 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_ci /* Allocate and initialize V4L video device */ 17758c2ecf20Sopenharmony_ci cx231xx_video_dev_init(dev, dev->udev, 17768c2ecf20Sopenharmony_ci &dev->v4l_device, &cx231xx_mpeg_template, "mpeg"); 17778c2ecf20Sopenharmony_ci q = &dev->mpegq; 17788c2ecf20Sopenharmony_ci q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 17798c2ecf20Sopenharmony_ci q->io_modes = VB2_USERPTR | VB2_MMAP | VB2_DMABUF | VB2_READ; 17808c2ecf20Sopenharmony_ci q->drv_priv = dev; 17818c2ecf20Sopenharmony_ci q->buf_struct_size = sizeof(struct cx231xx_buffer); 17828c2ecf20Sopenharmony_ci q->ops = &cx231xx_video_qops; 17838c2ecf20Sopenharmony_ci q->mem_ops = &vb2_vmalloc_memops; 17848c2ecf20Sopenharmony_ci q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 17858c2ecf20Sopenharmony_ci q->min_buffers_needed = 1; 17868c2ecf20Sopenharmony_ci q->lock = &dev->lock; 17878c2ecf20Sopenharmony_ci err = vb2_queue_init(q); 17888c2ecf20Sopenharmony_ci if (err) 17898c2ecf20Sopenharmony_ci return err; 17908c2ecf20Sopenharmony_ci dev->v4l_device.queue = q; 17918c2ecf20Sopenharmony_ci 17928c2ecf20Sopenharmony_ci err = video_register_device(&dev->v4l_device, 17938c2ecf20Sopenharmony_ci VFL_TYPE_VIDEO, -1); 17948c2ecf20Sopenharmony_ci if (err < 0) { 17958c2ecf20Sopenharmony_ci dprintk(3, "%s: can't register mpeg device\n", dev->name); 17968c2ecf20Sopenharmony_ci v4l2_ctrl_handler_free(&dev->mpeg_ctrl_handler.hdl); 17978c2ecf20Sopenharmony_ci return err; 17988c2ecf20Sopenharmony_ci } 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci dprintk(3, "%s: registered device video%d [mpeg]\n", 18018c2ecf20Sopenharmony_ci dev->name, dev->v4l_device.num); 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci return 0; 18048c2ecf20Sopenharmony_ci} 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_ciMODULE_FIRMWARE(CX231xx_FIRM_IMAGE_NAME); 1807