unsigned char mtv23x_spi_read(unsigned char page, unsigned char reg) { int ret; u8 out_buf[4], in_buf[4]; struct spi_message msg; struct spi_transfer msg_xfer = { .tx_buf = out_buf, .rx_buf = in_buf, .len = 4, .cs_change = 0, .delay_usecs = 0 }; #ifdef RTV_SPI_HIGH_SPEED_ENABLE if (g_bRtvSpiHighSpeed == TRUE) msg_xfer.speed_hz = SPI_SPEED_HIGH_Hz; else msg_xfer.speed_hz = SPI_SPEED_NORMAL_Hz; #endif out_buf[0] = 0x90 | page; out_buf[1] = reg; out_buf[2] = 1; /* Read size */ spi_message_init(&msg); spi_message_add_tail(&msg_xfer, &msg); ret = spi_sync(mtv_spi, &msg); if (ret) { DMBERR("error: %d\n", ret); return 0xFF; } #if 0 DMBMSG("0x%02X 0x%02X 0x%02X 0x%02X\n", in_buf[0], in_buf[1], in_buf[2], in_buf[3]); #endif return in_buf[SPI_CMD_SIZE]; } void mtv23x_spi_read_burst(unsigned char page, unsigned char reg, unsigned char *buf, int size) { int ret; u8 out_buf[SPI_CMD_SIZE]; struct spi_message msg; struct spi_transfer msg_xfer0 = { .tx_buf = out_buf, .rx_buf = buf, .len = SPI_CMD_SIZE, .cs_change = 0, .delay_usecs = 0 }; struct spi_transfer msg_xfer1 = { .tx_buf = buf, .rx_buf = buf, .len = size, .cs_change = 0, .delay_usecs = 0 }; #ifdef RTV_SPI_HIGH_SPEED_ENABLE if (g_bRtvSpiHighSpeed == TRUE) msg_xfer.speed_hz = SPI_SPEED_HIGH_Hz; else msg_xfer.speed_hz = SPI_SPEED_NORMAL_Hz; if (g_bRtvSpiHighSpeed == TRUE) msg_xfer1.speed_hz = SPI_SPEED_HIGH_Hz; else msg_xfer1.speed_hz = SPI_SPEED_NORMAL_Hz; #endif if (page > 15) { /* 0 ~ 15: not SPI memory */ out_buf[0] = 0xA0; /* Memory read */ out_buf[1] = 0x00; out_buf[2] = 188; /* Fix */ } else { out_buf[0] = 0x90 | page; /* Register read */ out_buf[1] = reg; out_buf[2] = size; } spi_message_init(&msg); spi_message_add_tail(&msg_xfer0, &msg); spi_message_add_tail(&msg_xfer1, &msg); ret = spi_sync(mtv_spi, &msg); if (ret) DMBERR("1 error: %d\n", ret); } void mtv23x_spi_write(unsigned char page, unsigned char reg, unsigned char val) { u8 out_buf[4]; u8 in_buf[4]; struct spi_message msg; struct spi_transfer msg_xfer = { .tx_buf = out_buf, .rx_buf = in_buf, .len = 4, .cs_change = 0, .delay_usecs = 0 }; int ret; #ifdef RTV_SPI_HIGH_SPEED_ENABLE if (g_bRtvSpiHighSpeed == TRUE) msg_xfer.speed_hz = SPI_SPEED_HIGH_Hz; else msg_xfer.speed_hz = SPI_SPEED_NORMAL_Hz; #endif out_buf[0] = 0x80 | page; out_buf[1] = reg; out_buf[2] = 1; /* size */ out_buf[3] = val; spi_message_init(&msg); spi_message_add_tail(&msg_xfer, &msg); ret = spi_sync(mtv_spi, &msg); if (ret) DMBERR("error: %d\n", ret); }
unsigned char mtv222_spi_read(unsigned char page, unsigned char reg) { int ret; static u8 out_buf[4] __attribute__((aligned(8))); static u8 in_buf[4] __attribute__((aligned(8))); struct spi_message msg; struct spi_transfer msg_xfer = { .tx_buf = out_buf, .rx_buf = in_buf, .len = 4, .cs_change = 0, .delay_usecs = 0 }; out_buf[0] = 0x90 | page; out_buf[1] = reg; out_buf[2] = 1; /* Read size */ spi_message_init(&msg); spi_message_add_tail(&msg_xfer, &msg); ret = spi_sync(mtv_spi, &msg); if (ret) { DMBERR("error: %d\n", ret); return 0xFF; } #if 0 DMBMSG("0x%02X 0x%02X 0x%02X 0x%02X\n", in_buf[0], in_buf[1], in_buf[2], in_buf[3]); #endif return in_buf[SPI_CMD_SIZE]; } void mtv222_spi_read_burst(unsigned char page, unsigned char reg, unsigned char *buf, int size) { int ret; static u8 out_buf[SPI_CMD_SIZE] __attribute__((aligned(8))); struct spi_message msg; struct spi_transfer msg_xfer0 = { .tx_buf = out_buf, .rx_buf = buf, .len = SPI_CMD_SIZE, .cs_change = 0, .delay_usecs = 0 }; struct spi_transfer msg_xfer1 = { .tx_buf = buf, .rx_buf = buf, .len = size, .cs_change = 0, .delay_usecs = 0 }; if (page > 15) { /* 0 ~ 15: not SPI memory */ out_buf[0] = 0xA0; /* Memory read */ out_buf[1] = 0x00; out_buf[2] = 188; /* Fix */ } else { out_buf[0] = 0x90 | page; /* Register read */ out_buf[1] = reg; out_buf[2] = size; } spi_message_init(&msg); spi_message_add_tail(&msg_xfer0, &msg); spi_message_add_tail(&msg_xfer1, &msg); ret = spi_sync(mtv_spi, &msg); if (ret) DMBERR("1 error: %d\n", ret); } void mtv222_spi_write(unsigned char page, unsigned char reg, unsigned char val) { static u8 out_buf[4] __attribute__((aligned(8))); static u8 in_buf[4] __attribute__((aligned(8))); struct spi_message msg; struct spi_transfer msg_xfer = { .tx_buf = out_buf, .rx_buf = in_buf, .len = 4, .cs_change = 0, .delay_usecs = 0 }; int ret; out_buf[0] = 0x80 | page; out_buf[1] = reg; out_buf[2] = 1; /* size */ out_buf[3] = val; spi_message_init(&msg); spi_message_add_tail(&msg_xfer, &msg); ret = spi_sync(mtv_spi, &msg); if (ret) DMBERR("error: %d\n", ret); } void mtv222_spi_recover(unsigned char *buf, unsigned int size) { int ret; struct spi_message msg; struct spi_transfer msg_xfer = { .tx_buf = buf, .rx_buf = buf, .len = size, .cs_change = 0, .delay_usecs = 0, }; memset(buf, 0xFF, size); spi_message_init(&msg); spi_message_add_tail(&msg_xfer, &msg); ret = spi_sync(mtv_spi, &msg); if (ret) DMBERR("error: %d\n", ret); }
static ssize_t mtv250_read(struct file *filp, char *buf, size_t count, loff_t *pos) { int ret = -ENODEV; #if defined(RTV_IF_SPI) int copy_bytes; unsigned int copy_offset; MTV250_TS_PKT_INFO *tsp = NULL; #ifdef MTV250_NON_BLOCKING_READ_MODE ssize_t read_len = 0; #else ssize_t read_len = count; #endif if(count == 0) { DMBERR("[mtv250_read] Invalid length: %d.\n", count); return -EAGAIN; } do { #ifndef MTV250_NON_BLOCKING_READ_MODE /* To release the read() of application as possible as soon, we use a queue count only. */ ret = wait_event_interruptible(mtv250_cb_ptr->read_wq, mtv250_tsp_queue.cnt || mtv250_cb_ptr->stop); if(ret < 0) { mtv250_cb_ptr->stop = 1; // In case, ERESTARTSYS DMBERR("[mtv250_read] woken up fail: %d\n", ret); goto read_fail; } if(mtv250_cb_ptr->stop) { DMBMSG("[mtv250_read] Device stopped. q:%d, stop:%d\n", mtv250_tsp_queue.cnt, mtv250_cb_ptr->stop); ret = -ENODEV; goto read_fail; } #endif if(mtv250_cb_ptr->prev_tsp == NULL) { tsp = mtv250_get_tsp(); /* Get a new tsp from tsp_queue. */ if(tsp == NULL) { ret = -EAGAIN; #ifdef MTV250_NON_BLOCKING_READ_MODE break; // Stop #else DMBERR("[mtv250_read] Abnormal case\n"); goto read_fail; #endif } copy_offset = 0; mtv250_cb_ptr->prev_tsp = tsp; // Save to use in next time if not finishded. mtv250_cb_ptr->prev_org_tsp_size = tsp->len; } else { tsp = mtv250_cb_ptr->prev_tsp; copy_offset = mtv250_cb_ptr->prev_org_tsp_size - tsp->len; } copy_bytes = MIN(tsp->len, count); ret = copy_to_user(buf, (&tsp->msc_buf[1] + copy_offset), copy_bytes); if (ret < 0) { DMBERR("[mtv250_read] copy user fail: %d\n", ret); ret = -EFAULT; goto read_fail; } else { //DMBMSG("[mtv250_read] copy user ret: %d\n", ret); #ifdef MTV250_NON_BLOCKING_READ_MODE read_len += copy_bytes; #endif buf += copy_bytes; count -= copy_bytes; tsp->len -= copy_bytes; if(tsp->len == 0) { mtv250_free_tsp(tsp); if(mtv250_cb_ptr->prev_tsp == tsp) mtv250_cb_ptr->prev_tsp = NULL; /* All used. */ } } } while(count != 0); return read_len; read_fail: if(mtv250_cb_ptr->prev_tsp != NULL) { mtv250_free_tsp(mtv250_cb_ptr->prev_tsp); mtv250_cb_ptr->prev_tsp = NULL; } #ifndef MTV250_NON_BLOCKING_READ_MODE /* Complete the read()*/ if(mtv250_cb_ptr->stop) { complete(&mtv250_cb_ptr->read_exit); // } #endif #endif // #if defined(RTV_IF_SPI) return ret; }
static int mtv250_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) #endif { int ret = 0; void __user *argp = (void __user *)arg; RTV_IOCTL_REGISTER_ACCESS ioctl_register_access; RTV_IOCTL_TEST_GPIO_INFO gpio_info; U8 reg_page = 0; UINT lock_mask; UINT isdbt_ch_num; RTV_ISDBT_TMCC_INFO isdbt_tmcc_info; IOCTL_ISDBT_SIGNAL_INFO isdbt_signal_info; IOCTL_ISDBT_LGE_TUNER_INFO lge_tuner_info; switch( cmd ) { case IOCTL_ISDBT_POWER_ON: // with adc clk type mtv250_cb_ptr->tv_mode = DMB_TV_MODE_1SEG; mtv250_cb_ptr->country_band_type = RTV_COUNTRY_BAND_JAPAN; DMBMSG("[mtv] IOCTL_ISDBT_POWER_ON: country_band_type(%d)\n", mtv250_cb_ptr->country_band_type); ret = mtv250_power_on(); if(ret != 0) { ret = -EFAULT; goto IOCTL_EXIT; } break; case IOCTL_ISDBT_POWER_OFF: DMBMSG("[mtv] IOCTL_ISDBT_POWER_OFF\n"); mtv250_power_off(); break; case IOCTL_ISDBT_SCAN_FREQ: if (copy_from_user(&isdbt_ch_num, argp, sizeof(UINT))) { ret = -EFAULT; goto IOCTL_EXIT; } ret = rtvISDBT_ScanFrequency(isdbt_ch_num); // DMBMSG("[mtv] ISDBT SCAN(%d) result: %d\n", isdbt_ch_num, ret); if(ret != RTV_SUCCESS) { ret = -EFAULT; goto IOCTL_EXIT; } break; case IOCTL_ISDBT_SET_FREQ: if (copy_from_user(&isdbt_ch_num, argp, sizeof(UINT))) { ret = -EFAULT; goto IOCTL_EXIT; } // DMBMSG("[mtv] IOCTL_ISDBT_SET_FREQ: %d\n", isdbt_ch_num); ret=rtvISDBT_SetFrequency(isdbt_ch_num); if(ret != RTV_SUCCESS) { DMBERR("[mtv] IOCTL_ISDBT_SET_FREQ error %d\n", ret); ret = -EFAULT; goto IOCTL_EXIT; } break; case IOCTL_ISDBT_GET_LOCK_STATUS: // DMBMSG("[mtv] IOCTL_ISDBT_GET_LOCK_STATUS\n"); lock_mask=rtvISDBT_GetLockStatus(); if (copy_to_user(argp,&lock_mask, sizeof(UINT))) { ret = -EFAULT; goto IOCTL_EXIT; } break; case IOCTL_ISDBT_GET_TMCC: // DMBMSG("[mtv] IOCTL_ISDBT_GET_TMCC\n"); rtvISDBT_GetTMCC(&isdbt_tmcc_info); if (copy_to_user(argp,&isdbt_tmcc_info, sizeof(RTV_ISDBT_TMCC_INFO))) { ret = -EFAULT; goto IOCTL_EXIT; } break; case IOCTL_ISDBT_GET_SIGNAL_INFO: // DMBMSG("[mtv] IOCTL_ISDBT_GET_SIGNAL_INFO\n"); isdbt_signal_info.ber = rtvISDBT_GetBER(); if(isdbt_signal_info.ber > 1500) isdbt_signal_info.ber = 100000; isdbt_signal_info.cnr = rtvISDBT_GetCNR() / RTV_ISDBT_CNR_DIVIDER; isdbt_signal_info.cnr = 10 * isdbt_signal_info.cnr; isdbt_signal_info.per = rtvISDBT_GetPER() * 3125; isdbt_signal_info.rssi = rtvISDBT_GetRSSI() / RTV_ISDBT_RSSI_DIVIDER; if (copy_to_user(argp, &isdbt_signal_info, sizeof(IOCTL_ISDBT_SIGNAL_INFO))) { ret = -EFAULT; goto IOCTL_EXIT; } break; case IOCTL_ISDBT_LGE_GET_TUNER_INFO: // lge_tuner_info.LOCK = rtvISDBT_GetLockStatus() == RTV_ISDBT_CHANNEL_LOCK_OK ? 1: 0; lge_tuner_info.CNo = rtvISDBT_GetCNR() / RTV_ISDBT_CNR_DIVIDER; lge_tuner_info.CNo = 10 * lge_tuner_info.CNo; lge_tuner_info.BER = rtvISDBT_GetBER(); if(lge_tuner_info.BER > 1500) lge_tuner_info.BER = 100000; lge_tuner_info.PER = rtvISDBT_GetPER() * 3125; #if 1 if(lge_tuner_info.LOCK == 0) lge_tuner_info.BER = lge_tuner_info.PER = 100000; #endif lge_tuner_info.AGC= rtvISDBT_GetAGC(); lge_tuner_info.RSSI= rtvISDBT_GetRSSI() / RTV_ISDBT_RSSI_DIVIDER; // temp!!!! lge_tuner_info.start_ts_int_cnt = mtv250_cb_ptr->start_ts_int_cnt; lge_tuner_info.ovf_err_cnt = mtv250_cb_ptr->ovf_err_cnt; if (copy_to_user(argp, &lge_tuner_info, sizeof(IOCTL_ISDBT_LGE_TUNER_INFO))) { ret = -EFAULT; goto IOCTL_EXIT; } break; case IOCTL_ISDBT_START_TS: RTV_GUARD_LOCK; mtv250_cb_ptr->start_ts_int_cnt = 0; mtv250_cb_ptr->ovf_err_cnt = 0; mtv250_cb_ptr->max_read_jiffies = 0; rtv_StreamEnable(); RTV_GUARD_FREE; break; case IOCTL_ISDBT_STOP_TS: rtvISDBT_DisableStreamOut(); mtv250_reset_tsp(); break; case IOCTL_TEST_DMB_POWER_ON: DMBMSG("[mtv250_ioctl] IOCTL_TEST_DMB_POWER_ON\n"); RTV_MASTER_CHIP_SEL; rtvOEM_PowerOn(1); mtv250_cb_ptr->is_power_on = TRUE; break; case IOCTL_TEST_DMB_POWER_OFF: RTV_MASTER_CHIP_SEL; rtvOEM_PowerOn(0); mtv250_cb_ptr->is_power_on = FALSE; break; case IOCTL_REGISTER_READ: if(mtv250_cb_ptr->is_power_on == FALSE) { DMBMSG("[mtv] Power Down state!Must Power ON\n"); ret = -EFAULT; goto IOCTL_EXIT; } if (copy_from_user(&ioctl_register_access, argp, sizeof(RTV_IOCTL_REGISTER_ACCESS))) { ret = -EFAULT; goto IOCTL_EXIT; } //DMBMSG("[mtv] IOCTL_REGISTER_READ: [%d] 0x%02X\n", ioctl_register_access.page, ioctl_register_access.Addr); switch( mtv250_cb_ptr->tv_mode ) { case DMB_TV_MODE_TDMB: case DMB_TV_MODE_FM: switch( ioctl_register_access.page ) { case 6: reg_page = 0x06; break; // OFDM case 7: reg_page = 0x09; break; // FEC case 8: reg_page = 0x0A; break; // FEC default: reg_page = mtv_reg_page_addr[ioctl_register_access.page]; } break; case DMB_TV_MODE_1SEG: switch( ioctl_register_access.page ) { case 6: reg_page = 0x02; break; // OFDM case 7: reg_page = 0x03; break; // FEC default: reg_page = mtv_reg_page_addr[ioctl_register_access.page]; } break; default: break; } RTV_REG_MAP_SEL(reg_page); ioctl_register_access.data[0] = RTV_REG_GET(ioctl_register_access.Addr); if (copy_to_user(argp, &ioctl_register_access, sizeof(RTV_IOCTL_REGISTER_ACCESS))) { ret = -EFAULT; goto IOCTL_EXIT; } break; case IOCTL_REGISTER_WRITE: if(mtv250_cb_ptr->is_power_on == FALSE) { DMBMSG("[mtv] Power Down state!Must Power ON\n"); ret = -EFAULT; goto IOCTL_EXIT; } if (copy_from_user(&ioctl_register_access, argp, sizeof(RTV_IOCTL_REGISTER_ACCESS))) { ret = -EFAULT; goto IOCTL_EXIT; } switch( mtv250_cb_ptr->tv_mode ) { case DMB_TV_MODE_TDMB: case DMB_TV_MODE_FM: switch( ioctl_register_access.page ) { case 6: reg_page = 0x06; break; // OFDM case 7: reg_page = 0x09; break; // FEC case 8: reg_page = 0x0A; break; // FEC default: reg_page = mtv_reg_page_addr[ioctl_register_access.page]; } break; case DMB_TV_MODE_1SEG: switch( ioctl_register_access.page ) { case 6: reg_page = 0x02; break; // OFDM case 7: reg_page = 0x03; break; // FEC default: reg_page = mtv_reg_page_addr[ioctl_register_access.page]; } break; default: break; } RTV_REG_MAP_SEL(reg_page); RTV_REG_SET(ioctl_register_access.Addr, ioctl_register_access.data[0]); break; case IOCTL_TEST_GPIO_SET: if(mtv250_cb_ptr->is_power_on == FALSE) { DMBMSG("[mtv] Power Down state!Must Power ON\n"); ret = -EFAULT; goto IOCTL_EXIT; } if (copy_from_user(&gpio_info, argp, sizeof(RTV_IOCTL_TEST_GPIO_INFO))) { ret = -EFAULT; goto IOCTL_EXIT; } gpio_set_value(gpio_info.pin, gpio_info.value); break; case IOCTL_TEST_GPIO_GET: if(mtv250_cb_ptr->is_power_on == FALSE) { DMBMSG("[mtv] Power Down state!Must Power ON\n"); ret = -EFAULT; goto IOCTL_EXIT; } if (copy_from_user(&gpio_info, argp, sizeof(RTV_IOCTL_TEST_GPIO_INFO))) { ret = -EFAULT; goto IOCTL_EXIT; } gpio_info.value = gpio_get_value(gpio_info.pin); if(copy_to_user(argp, &gpio_info, sizeof(RTV_IOCTL_TEST_GPIO_INFO))) { ret = -EFAULT; goto IOCTL_EXIT; } break; default: DMBERR("[mtv] Invalid ioctl command: %d\n", cmd); ret = -ENOTTY; break; } IOCTL_EXIT: return ret; }
static int mtv250_init_device(void) { int ret = 0; mtv250_cb_ptr = kzalloc(sizeof(struct mtv250_cb), GFP_KERNEL); if (!mtv250_cb_ptr) { DMBERR("[mtv250_init_device] kzalloc failed\n"); return -ENOMEM; } mtv250_cb_ptr->is_power_on = 0; // for prove() mtv250_cb_ptr->stop = 0; mtv250_configure_gpio(); #if defined(RTV_IF_MPEG2_SERIAL_TSIF) || defined(RTV_IF_SPI_SLAVE) || defined(RTV_IF_MPEG2_PARALLEL_TSIF) || defined(RTV_IF_QUALCOMM_TSIF) ret = mtv250_i2c_init(); if(ret < 0) { DMBERR("RAONTV I2C driver registe failed\n"); goto err_free_mem; } #elif defined(RTV_IF_SPI) ret = mtv250_spi_init(); if(ret < 0) { DMBERR("RAONTV SPI driver registe failed\n"); goto err_free_mem; } /* Init tsp queue.*/ mtv250_init_tsp_queue(); ret = mtv250_create_tsp_pool(); if(ret < 0) { DMBERR("RAONTV SPI TS buffer creation failed\n"); goto err_free_mem; } #endif #if defined(RTV_IF_SPI) || (defined(RTV_TDMB_ENABLE) && !defined(RTV_TDMB_FIC_POLLING_MODE)) mtv250_cb_ptr->isr_thread_cb = NULL; if ((ret=mtv250_isr_thread_run()) != 0) { DMBERR("[mtv250_power_on] mtv250_isr_thread_run() error\n"); goto err_free_mem; } // interupt name ret = request_irq(gpio_to_irq(RAONTV_IRQ_INT), mtv250_isr, IRQ_TYPE_EDGE_FALLING, RAONTV_DEV_NAME, NULL); if (ret != 0) { DMBERR("[mtv250_init_device] Failed to install irq (%d)\n", ret); mtv250_isr_thread_stop(); goto err_free_mem; } #endif return 0; err_free_mem: kfree(mtv250_cb_ptr); mtv250_cb_ptr = NULL; return ret; }