1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261 |
- /*
- *
- * drivers/media/tdmb/isdbt_port_mtv222.c
- *
- * isdbt driver
- *
- * Copyright (C) (2014, Samsung Electronics)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
- #include <linux/kernel.h>
- #include <linux/errno.h>
- #include <linux/device.h>
- #include <linux/init.h>
- #include <linux/types.h>
- #include <linux/fcntl.h>
- #include <linux/workqueue.h>
- #include <linux/irq.h>
- #include <linux/interrupt.h>
- #include <linux/io.h>
- #include <linux/fs.h>
- #include <linux/uaccess.h>
- #include <linux/time.h>
- #include <linux/timer.h>
- #include <linux/vmalloc.h>
- #include "isdbt.h"
- #include "isdbt_port_mtv222.h"
- #ifndef VM_RESERVED /* for kernel 3.10 */
- #define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP)
- #endif
- extern void mtv222_set_port_if(unsigned long interface);
- static bool mtv222_on_air = false;
- struct MTV222_CB *mtv222_cb_ptr = NULL;
- #ifdef _MTV_KERNEL_FILE_DUMP_ENABLE
- struct file *mtv_ts_filp = NULL;
- #endif
- static void tsb_enqueue(unsigned char *ts_chunk)
- {
- #ifdef DEBUG_TSP_BUF
- int readi, writei, num_euqueued_tsp, num_euqueued_seg;
- #endif
- struct TSB_CB_INFO *tsb_cb = &mtv222_cb_ptr->tsb_cb;
- if (!tsb_cb->tsbd) {
- DMBERR("Not memory mapped\n");
- return;
- }
- if (tsb_cb->tsbd->op_enabled) {
- /* Check if the specified tspb is the allocated tspb? */
- if (ts_chunk == tsb_cb->seg_buf[tsb_cb->enqueue_seg_idx]) {
- /* Update the next index of write-tsp. */
- tsb_cb->tsbd->write_idx = tsb_cb->avail_write_tspb_idx;
- /* Update the next index of segment. */
- tsb_cb->enqueue_seg_idx = tsb_cb->avail_seg_idx;
- #ifdef DEBUG_TSP_BUF
- readi = tsb_cb->tsbd->read_idx;
- writei = tsb_cb->tsbd->write_idx;
- if (writei > readi)
- num_euqueued_tsp = writei - readi;
- else if (writei < readi)
- num_euqueued_tsp = tsb_cb->num_total_tsp - (readi - writei);
- else
- num_euqueued_tsp = 0;
- mtv222_cb_ptr->max_enqueued_tsp_cnt
- = MAX(mtv222_cb_ptr->max_enqueued_tsp_cnt, num_euqueued_tsp);
- num_euqueued_seg = num_euqueued_tsp / tsb_cb->num_tsp_per_seg;
- mtv222_cb_ptr->max_enqueued_seg_cnt
- = MAX(mtv222_cb_ptr->max_enqueued_seg_cnt, num_euqueued_seg);
- #endif
- } else
- DMBERR("Invalid the enqueuing chunk address!\n");
- }
- }
- /* Get a TS buffer */
- static U8 *tsb_get(void)
- {
- int readi;
- int nwi; /* Next index of tsp buffer to be write. */
- struct TSB_CB_INFO *tsb_cb = &mtv222_cb_ptr->tsb_cb;
- unsigned char *tspb = NULL;
- int num_tsp_per_seg = tsb_cb->num_tsp_per_seg;
- #ifdef DEBUG_TSP_BUF
- int num_used_segment; /* Should NOT zero. */
- int write_seg_idx, read_seg_idx;
- #endif
- if (!tsb_cb->tsbd) {
- DMBERR("Not memory mapped\n");
- return NULL;
- }
- if (tsb_cb->tsbd->op_enabled) {
- readi = tsb_cb->tsbd->read_idx;
- /* Get the next avaliable index of segment to be write in the next time. */
- nwi = tsb_cb->avail_write_tspb_idx + num_tsp_per_seg;
- if (nwi >= tsb_cb->num_total_tsp)
- nwi = 0;
- if ((readi < nwi) || (readi >= (nwi + num_tsp_per_seg))) {
- tspb = tsb_cb->seg_buf[tsb_cb->avail_seg_idx];
- /* Update the writting index of tsp buffer. */
- tsb_cb->avail_write_tspb_idx = nwi;
- /* Update the avaliable index of segment to be write in the next time. */
- if (++tsb_cb->avail_seg_idx >= tsb_cb->num_total_seg)
- tsb_cb->avail_seg_idx = 0;
- #ifdef DEBUG_TSP_BUF
- write_seg_idx = tsb_cb->avail_seg_idx;
- read_seg_idx = readi / num_tsp_per_seg;
- if (write_seg_idx > read_seg_idx)
- num_used_segment = write_seg_idx - read_seg_idx;
- else
- num_used_segment
- = tsb_cb->num_total_seg - (read_seg_idx - write_seg_idx);
- DMBMSG("wseg_idx(%d), rseg_idx(%d), num_used_segment(%d)\n",
- write_seg_idx, read_seg_idx, num_used_segment);
- mtv222_cb_ptr->max_alloc_seg_cnt
- = MAX(mtv222_cb_ptr->max_alloc_seg_cnt, num_used_segment);
- #endif
- //DMBMSG("@@ readi(%d), next_writei(%d), avail_seg_idx(%d), tspb(0x%08lX)\n",
- // readi, nwi, tsb_cb->avail_seg_idx, (unsigned long)tspb);
- } else
- DMBERR("Full tsp buffer.\n");
- }
- return tspb;
- }
- static inline void tsb_free_mapping_area(void)
- {
- int i;
- unsigned int order;
- struct TSB_CB_INFO *tsb_cb = &mtv222_cb_ptr->tsb_cb;
- order = get_order(tsb_cb->seg_size);
- for (i = 0; i < tsb_cb->num_total_seg; i++) {
- if (tsb_cb->seg_buf[i]) {
- //DMBMSG("SEG[%d]: seg_buf(0x%lX)\n", i, (unsigned long)tsb_cb->seg_buf[i]);
- free_pages((unsigned long)tsb_cb->seg_buf[i], order);
- tsb_cb->seg_buf[i] = NULL;
- }
- }
- tsb_cb->seg_bufs_allocated = false;
- tsb_cb->seg_size = 0;
- tsb_cb->num_total_seg = 0;
- if (tsb_cb->tsbd) {
- order = get_order(tsb_cb->desc_size);
- free_pages((unsigned long)tsb_cb->tsbd, order);
- tsb_cb->tsbd = NULL;
- tsb_cb->desc_size = 0;
- }
- }
- static inline int tsb_alloc_mapping_area(unsigned int desc_size,
- unsigned int seg_size, int num_seg)
- {
- int i, ret;
- unsigned int order;
- struct TSB_CB_INFO *tsb_cb = &mtv222_cb_ptr->tsb_cb;
- /* Allocate the TSB descriptor. */
- order = get_order(desc_size);
- tsb_cb->tsbd
- = (struct TSB_DESC_INFO *)__get_dma_pages(GFP_KERNEL, order);
- if (!tsb_cb->tsbd) {
- DMBMSG("DESC allocation error\n");
- return -ENOMEM;
- }
- /* Allocate the TSB segments. */
- order = get_order(seg_size);
- DMBMSG("SEG order(%u)\n", order);
- if (order > MAX_ORDER) {
- DMBMSG("Invalid page order value of segment (%u)\n", order);
- ret = -ENOMEM;
- goto free_tsb;
- }
- for (i = 0; i < num_seg; i++) {
- tsb_cb->seg_buf[i] = (U8 *)__get_dma_pages(GFP_KERNEL, order);
- if (!tsb_cb->seg_buf[i]) {
- DMBMSG("SEG[%u] allocation error\n", i);
- ret = -ENOMEM;
- goto free_tsb;
- }
- }
- tsb_cb->seg_bufs_allocated = true;
- DMBMSG("Success\n");
- return 0;
- free_tsb:
- tsb_free_mapping_area();
- return ret;
- }
- static void mtv222_mmap_close(struct vm_area_struct *vma)
- {
- DMBMSG("Entered. mmap_completed(%d)\n", mtv222_cb_ptr->tsb_cb.mmap_completed);
- mtv222_cb_ptr->tsb_cb.mmap_completed = false;
- DMBMSG("Leaved...\n");
- }
- static const struct vm_operations_struct mtv222_mmap_ops = {
- .close = mtv222_mmap_close,
- };
- static int mtv222_mmap(struct file *filp, struct vm_area_struct *vma)
- {
- int ret, num_total_seg;
- unsigned int i, mmap_size, desc_size, seg_size;
- unsigned long pfn;
- unsigned long start = vma->vm_start;
- struct TSB_CB_INFO *tsb_cb = &mtv222_cb_ptr->tsb_cb;
- vma->vm_flags |= VM_RESERVED;
- vma->vm_ops = &mtv222_mmap_ops;
- mmap_size = vma->vm_end - vma->vm_start;
- #if 0
- DMBMSG("mmap_size(0x%X), vm_start(0x%lX), vm_page_prot(0x%lX)\n",
- mmap_size, vma->vm_start, vma->vm_page_prot);
- #endif
- if (mmap_size & (~PAGE_MASK)) {
- DMBERR("Must align with PAGE size\n");
- return -EINVAL;
- }
- if (tsb_cb->mmap_completed == true) {
- DMBERR("Already mapped!\n");
- return 0;
- }
- seg_size = vma->vm_pgoff << PAGE_SHIFT;
- num_total_seg = (mmap_size - PAGE_SIZE) / seg_size;
- desc_size = mmap_size - (num_total_seg * seg_size);
- /* Save */
- tsb_cb->desc_size = desc_size;
- tsb_cb->seg_size = seg_size;
- tsb_cb->num_total_seg = num_total_seg;
- #if 1
- DMBMSG("mmap_size(%u), seg_size(%u) #seg(%d), desc_size(%u)\n",
- mmap_size, seg_size, num_total_seg, desc_size);
- #endif
- if (num_total_seg > MAX_NUM_TSB_SEG) {
- DMBERR("Too large request #seg! kernel(%u), req(%d)\n",
- MAX_NUM_TSB_SEG, num_total_seg);
- return -ENOMEM;
- }
- if (desc_size > MAX_TSB_DESC_SIZE) {
- DMBERR("Too large request desc size! kernel(%u), req(%u)\n",
- MAX_TSB_DESC_SIZE, desc_size);
- return -ENOMEM;
- }
- if (seg_size > MAX_TSB_SEG_SIZE) {
- DMBERR("Too large request seg size! kernel(%u), req(%u)\n",
- MAX_TSB_SEG_SIZE, seg_size);
- return -ENOMEM;
- }
- if (!tsb_cb->tsbd) {
- DMBERR("TSB DESC was NOT allocated!\n");
- return -ENOMEM;
- }
- if (tsb_cb->seg_bufs_allocated == false) {
- DMBERR("TSB SEG are NOT allocated!\n");
- return -ENOMEM;
- }
- /* Map the shared informations. */
- pfn = virt_to_phys(tsb_cb->tsbd) >> PAGE_SHIFT;
- if (remap_pfn_range(vma, vma->vm_start, pfn, desc_size, vma->vm_page_prot)) {
- DMBERR("HDR remap_pfn_range() error!\n");
- ret = -EAGAIN;
- goto out;
- }
- /* Init descriptor except the addres of segments */
- tsb_cb->tsbd->op_enabled = 0;
- tsb_cb->tsbd->read_idx = 0;
- tsb_cb->tsbd->write_idx = 0;
- #if 0
- DMBMSG("tsbd(0x%lX), pfn(0x%lX), start(0x%lX)\n",
- (unsigned long)tsb_cb->tsbd, pfn, start);
- #endif
- start += desc_size; /* Avdance VMA. */
- /* Allocate and map the TSP buffer segments. */
- for (i = 0; i < num_total_seg; i++) {
- pfn = virt_to_phys(tsb_cb->seg_buf[i]) >> PAGE_SHIFT;
- #if 0
- DMBMSG("SEG[%d]: seg_buf(0x%lX) pfn(0x%lX) start(0x%lX)\n",
- i, (unsigned long)tsb_cb->seg_buf[i], pfn, start);
- #endif
- if (remap_pfn_range(vma, start, pfn, seg_size, vma->vm_page_prot)) {
- DMBERR("SEG[%u] remap_pfn_range() error!\n", i);
- ret = -EAGAIN;
- goto out;
- }
- tsb_cb->tsbd->seg_base[i] = start;
- start += seg_size;
- }
- tsb_cb->mmap_completed = true;
- return 0;
- out:
- return ret;
- }
- static void mtv222_power_off(void)
- {
- DMBMSG("mtv222_power_off\n");
- if (mtv222_cb_ptr->is_power_on) {
- mtv222_on_air = false;
- // isdbt_control_irq(false);
- isdbt_control_gpio(false);
- mtv222_cb_ptr->is_power_on = false;
- mtv222_cb_ptr->tsout_enabled = false;
- RTV_GUARD_DEINIT;
- }
- }
- static INLINE int __mtv222_power_on(unsigned long arg)
- {
- int ret;
- IOCTL_ISDBT_POWER_ON_INFO __user *argp
- = (IOCTL_ISDBT_POWER_ON_INFO __user *)arg;
- #if defined(RTV_IF_SPI) || defined(RTV_IF_CSI656_RAW_8BIT_ENABLE)
- if (get_user(mtv222_cb_ptr->intr_size, &argp->spi_intr_size[0]))
- return -EFAULT;
- DMBMSG("intr_size: %u\n", mtv222_cb_ptr->intr_size);
- mtv222_cb_ptr->cfged_tsp_chunk_size = 0;
- #endif
- if (get_user(mtv222_cb_ptr->country_band_type, &argp->country_band_type))
- return -EFAULT;
- mtv222_cb_ptr->tsout_enabled = false;
- mtv222_cb_ptr->cfged_svc = RTV_SERVICE_INVALID;
- ret = rtvISDBT_Initialize(mtv222_cb_ptr->country_band_type,
- mtv222_cb_ptr->intr_size);
- if (ret != RTV_SUCCESS) {
- DMBERR("Tuner initialization failed: %d\n", ret);
- if (put_user(ret, &argp->tuner_err_code))
- return -EFAULT;
- return -EIO; /* error occurred during the open() */
- }
- return ret;
- }
- static int mtv222_power_on(unsigned long arg)
- {
- int ret;
- IOCTL_ISDBT_POWER_ON_INFO __user *argp
- = (IOCTL_ISDBT_POWER_ON_INFO __user *)arg;
- DMBMSG("mtv222_power_on\n");
- if (mtv222_cb_ptr->is_power_on) {
- return 0;
- } else {
- isdbt_control_gpio(true);
- RTV_GUARD_INIT;
- mtv222_set_port_if((unsigned long)isdbt_get_if_handle());
- ret = __mtv222_power_on(arg);
- if (ret) {
- DMBERR("Tuner initialization failed: %d\n", ret);
- isdbt_control_gpio(false);
- if (put_user(ret, &argp->tuner_err_code))
- return -EFAULT;
- return ret;
- } else {
- // isdbt_control_irq(true);
- mtv222_cb_ptr->is_power_on = true;
- return 0;
- }
- }
- }
- #if defined(RTV_IF_SPI) || defined(RTV_IF_SPI_TSIFx)
- static unsigned long diff_jiffies_1st, diff_jiffies0, hours_cnt;
- #endif
- #define ISDBT_VALID_SVC_MASK (1<<RTV_SERVICE_UHF_ISDBT_1seg)
- /*============================================================================
- * Test IO control commands(0 ~ 10)
- *==========================================================================*/
- static int test_register_io(unsigned long arg, unsigned int cmd)
- {
- int ret = 0;
- unsigned int page, addr, write_data, read_cnt, i;
- U8 value;
- #if defined(RTV_IF_SPI) || defined(RTV_IF_SPI_TSIFx)
- unsigned long diff_jiffies1;
- unsigned int elapsed_ms;
- unsigned long param1;
- #endif
- U8 *reg_read_buf;
- U8 *src_ptr, *dst_ptr;
- IOCTL_REG_ACCESS_INFO __user *argp
- = (IOCTL_REG_ACCESS_INFO __user *)arg;
- if (mtv222_cb_ptr->is_power_on == FALSE) {
- DMBMSG("[mtv] Power Down state!Must Power ON\n");
- return -EFAULT;
- }
- if (get_user(page, &argp->page))
- return -EFAULT;
- if (get_user(addr, &argp->addr))
- return -EFAULT;
- RTV_GUARD_LOCK;
- switch (cmd) {
- case IOCTL_TEST_REG_SINGLE_READ:
- RTV_REG_MAP_SEL(page);
- value = RTV_REG_GET(addr);
- if (put_user(value, &argp->read_data[0])) {
- ret = -EFAULT;
- goto regio_exit;
- }
- break;
- case IOCTL_TEST_REG_BURST_READ:
- if (get_user(read_cnt, &argp->read_cnt)) {
- ret = -EFAULT;
- goto regio_exit;
- }
- reg_read_buf = kmalloc(MAX_NUM_MTV_REG_READ_BUF, GFP_KERNEL);
- if (reg_read_buf == NULL) {
- DMBERR("Register buffer allocation error\n");
- ret = -ENOMEM;
- goto regio_exit;
- }
- RTV_REG_MAP_SEL(page);
- RTV_REG_BURST_GET(addr, reg_read_buf, read_cnt);
- src_ptr = ®_read_buf[0];
- dst_ptr = argp->read_data;
- for (i = 0; i< read_cnt; i++, src_ptr++, dst_ptr++) {
- if(put_user(*src_ptr, dst_ptr)) {
- ret = -EFAULT;
- break;
- }
- }
- kfree(reg_read_buf);
- break;
- case IOCTL_TEST_REG_WRITE:
- if (get_user(write_data, &argp->write_data)) {
- ret = -EFAULT;
- goto regio_exit;
- }
- RTV_REG_MAP_SEL(page);
- RTV_REG_SET(addr, write_data);
- break;
- case IOCTL_TEST_REG_SPI_MEM_READ:
- #if defined(RTV_IF_SPI)
- if (get_user(write_data, &argp->write_data)) {
- ret = -EFAULT;
- goto regio_exit;
- }
- if (get_user(read_cnt, &argp->read_cnt)) {
- ret = -EFAULT;
- goto regio_exit;
- }
- if (get_user(param1, &argp->param1)) {
- ret = -EFAULT;
- goto regio_exit;
- }
- reg_read_buf = kmalloc(MAX_NUM_MTV_REG_READ_BUF, GFP_KERNEL);
- if (reg_read_buf == NULL) {
- DMBERR("Register buffer allocation error\n");
- ret = -ENOMEM;
- goto regio_exit;
- }
- if (param1 == 0) {
- diff_jiffies_1st = diff_jiffies0 = get_jiffies_64();
- hours_cnt = 0;
- DMBMSG("START [AGING SPI Memory Test with Single IO]\n");
- }
- RTV_REG_MAP_SEL(page);
- RTV_REG_SET(addr, write_data);
- RTV_REG_MAP_SEL(SPI_MEM_PAGE);
- RTV_REG_BURST_GET(0x10, reg_read_buf, read_cnt);
- RTV_REG_MAP_SEL(page);
- value = RTV_REG_GET(addr);
- diff_jiffies1 = get_jiffies_64();
- elapsed_ms = jiffies_to_msecs(diff_jiffies1-diff_jiffies0);
- if (elapsed_ms >= (1000 * 60 * 60)) {
- diff_jiffies0 = get_jiffies_64(); /* Re-start */
- hours_cnt++;
- DMBMSG("\t %lu hours elaspesed...\n", hours_cnt);
- }
- if (write_data != value) {
- unsigned int min, sec;
- elapsed_ms = jiffies_to_msecs(diff_jiffies1-diff_jiffies_1st);
- sec = elapsed_ms / 1000;
- min = sec / 60;
- DMBMSG("END [AGING SPI Memory Test with Single IO]\n");
- DMBMSG("Total minutes: %u\n", min);
- }
- if (put_user(value, &argp->read_data[0]))
- ret = -EFAULT;
- kfree(reg_read_buf);
- #else
- DMBERR("Not SPI interface\n");
- #endif
- break;
- case IOCTL_TEST_REG_ONLY_SPI_MEM_READ:
- #if defined(RTV_IF_SPI)
- if (get_user(read_cnt, &argp->read_cnt)) {
- ret = -EFAULT;
- goto regio_exit;
- }
- if (get_user(write_data, &argp->write_data)) {
- ret = -EFAULT;
- goto regio_exit;
- }
- reg_read_buf = kmalloc(MAX_NUM_MTV_REG_READ_BUF, GFP_KERNEL);
- if (reg_read_buf == NULL) {
- DMBERR("Register buffer allocation error\n");
- ret = -ENOMEM;
- goto regio_exit;
- }
- if (write_data == 0) /* only one-time page selection */
- RTV_REG_MAP_SEL(page);
- RTV_REG_BURST_GET(addr, reg_read_buf, read_cnt);
-
- src_ptr = reg_read_buf;
- dst_ptr = argp->read_data;
- for (i = 0; i< read_cnt; i++, src_ptr++, dst_ptr++) {
- if(put_user(*src_ptr, dst_ptr)) {
- ret = -EFAULT;
- break;
- }
- }
- kfree(reg_read_buf);
- #else
- DMBERR("Not SPI interface\n");
- #endif
- break;
- default:
- break;
- }
- regio_exit:
- RTV_GUARD_FREE;
- return 0;
- }
- static int test_gpio(unsigned long arg, unsigned int cmd)
- {
- unsigned int pin, value;
- IOCTL_GPIO_ACCESS_INFO __user *argp = (IOCTL_GPIO_ACCESS_INFO __user *)arg;
- if (get_user(pin, &argp->pin))
- return -EFAULT;
- switch (cmd) {
- case IOCTL_TEST_GPIO_SET:
- if(get_user(value, &argp->value))
- return -EFAULT;
- gpio_set_value(pin, value);
- break;
- case IOCTL_TEST_GPIO_GET:
- value = gpio_get_value(pin);
- if(put_user(value, &argp->value))
- return -EFAULT;
- }
- return 0;
- }
- static void test_power_on_off(unsigned int cmd)
- {
- switch (cmd) {
- case IOCTL_TEST_MTV_POWER_ON:
- DMBMSG("IOCTL_TEST_MTV_POWER_ON\n");
- if (mtv222_cb_ptr->is_power_on == FALSE) {
- isdbt_control_gpio(true);
- rtvISDBT_Initialize(RTV_COUNTRY_BAND_BRAZIL, 16*188);
- mtv222_cb_ptr->is_power_on = TRUE;
- }
- break;
- case IOCTL_TEST_MTV_POWER_OFF:
- if(mtv222_cb_ptr->is_power_on == TRUE) {
- isdbt_control_gpio(false);
- mtv222_cb_ptr->is_power_on = FALSE;
- }
- break;
- }
- }
- /*==============================================================================
- * TDMB IO control commands(30 ~ 49)
- *============================================================================*/
- static INLINE int mtv222_get_signal_qual_info(unsigned long arg)
- {
- IOCTL_ISDBT_SIGNAL_QUAL_INFO sig;
- void __user *argp = (void __user *)arg;
- sig.lock_mask = rtvISDBT_GetLockStatus();
- sig.rssi = rtvISDBT_GetRSSI();
- sig.ber_layer_A = rtvISDBT_GetBER();
- sig.ber_layer_B = 0;
- sig.per_layer_A = rtvISDBT_GetPER();
- sig.per_layer_B = 0;
- sig.cnr_layer_A = rtvISDBT_GetCNR();
- sig.ant_level_layer_A = rtvISDBT_GetAntennaLevel(sig.cnr_layer_A);
- sig.cnr_layer_B = 0;
- sig.ant_level_layer_B = 0;
- if (copy_to_user(argp, &sig, sizeof(IOCTL_ISDBT_SIGNAL_QUAL_INFO)))
- return -EFAULT;
- SHOW_ISDBT_DEBUG_STAT;
- return 0;
- }
- static INLINE int mtv222_get_cnr(unsigned long arg)
- {
- int cnr = (int)rtvISDBT_GetCNR();
- if (put_user(cnr, (int *)arg))
- return -EFAULT;
- SHOW_ISDBT_DEBUG_STAT;
- return 0;
- }
- static INLINE int mtv222_get_rssi(unsigned long arg)
- {
- int rssi = rtvISDBT_GetRSSI();
- if (put_user(rssi, (int *)arg))
- return -EFAULT;
- SHOW_ISDBT_DEBUG_STAT;
- return 0;
- }
- static INLINE int mtv222_get_ber_per_info(unsigned long arg)
- {
- IOCTL_ISDBT_BER_PER_INFO info;
- void __user *argp = (void __user *)arg;
- info.ber_layer_A = rtvISDBT_GetBER();
- info.ber_layer_B = 0;
- info.per_layer_A = rtvISDBT_GetPER();
- info.per_layer_B = 0;
- if (copy_to_user(argp, &info, sizeof(IOCTL_ISDBT_BER_PER_INFO)))
- return -EFAULT;
- SHOW_ISDBT_DEBUG_STAT;
- return 0;
- }
- static INLINE void mtv222_disable_standby_mode(unsigned long arg)
- {
- rtvISDBT_StandbyMode(0);
- }
- static INLINE void mtv222_enable_standby_mode(unsigned long arg)
- {
- rtvISDBT_StandbyMode(1);
- }
- static INLINE int mtv222_get_lock_status(unsigned long arg)
- {
- unsigned int lock_mask = rtvISDBT_GetLockStatus();
- if (put_user(lock_mask, (unsigned int *)arg))
- return -EFAULT;
- return 0;
- }
- static INLINE int mtv222_get_signal_info(unsigned long arg)
- {
- IOCTL_ISDBT_SIGNAL_INFO sig;
- void __user *argp = (void __user *)arg;
- sig.lock_mask = rtvISDBT_GetLockStatus();
- sig.ber = rtvISDBT_GetBER();
- sig.cnr = rtvISDBT_GetCNR();
- sig.per = rtvISDBT_GetPER();
- sig.rssi = rtvISDBT_GetRSSI();
- sig.ant_level = rtvISDBT_GetAntennaLevel(sig.cnr);
- if (copy_to_user(argp, &sig, sizeof(IOCTL_ISDBT_SIGNAL_INFO)))
- return -EFAULT;
- SHOW_ISDBT_DEBUG_STAT;
- return 0;
- }
- static INLINE int mtv222_set_channel(unsigned long arg)
- {
- int ch_no;
- int ret = 0;
- unsigned int freq_khz, subch_id, intr_size;
- enum E_RTV_SERVICE_TYPE svc_type;
- enum E_RTV_BANDWIDTH_TYPE bw;
- IOCTL_ISDBT_SET_CH_INFO __user *argp
- = (IOCTL_ISDBT_SET_CH_INFO __user *)arg;
- if (get_user(freq_khz, &argp->freq_khz))
- return -EFAULT;
- if (get_user(subch_id, &argp->subch_id))
- return -EFAULT;
- if (get_user(svc_type, &argp->svc_type))
- return -EFAULT;
- if (get_user(bw, &argp->bandwidth))
- return -EFAULT;
- if (!((1<<svc_type) & ISDBT_VALID_SVC_MASK)) {
- DMBERR("Invaild service type: %d\n", svc_type);
- mtv222_cb_ptr->cfged_svc = RTV_SERVICE_INVALID;
- return -EINVAL;
- }
- DMBMSG("freq_khz(%u), subch_id(%u), svc_type(%u), bandwidth(%d)\n",
- freq_khz, subch_id, svc_type, bw);
- #if defined(RTV_IF_SPI)
- intr_size = mtv222_cb_ptr->intr_size;
- #else
- intr_size = 0;
- #endif
- mtv222_cb_ptr->cfged_svc = svc_type;
- mtv222_cb_ptr->freq_khz = freq_khz;
- ch_no = RTV_ISDBT_FREQ2CHNUM(mtv222_cb_ptr->country_band_type, freq_khz);
- ret = rtvISDBT_SetFrequency(ch_no);
- if (ret != RTV_SUCCESS) {
- DMBERR("failed: %d\n", ret);
- if (put_user(ret, &argp->tuner_err_code))
- return -EFAULT;
- return -EIO;
- }
- DMBMSG("Leave...\n");
- return 0;
- }
- static INLINE int mtv222_scan_channel(unsigned long arg)
- {
- int ch_no;
- int ret;
- unsigned int freq_khz, subch_id, intr_size;
- enum E_RTV_SERVICE_TYPE svc_type;
- enum E_RTV_BANDWIDTH_TYPE bw;
- IOCTL_ISDBT_SCAN_INFO __user *argp
- = (IOCTL_ISDBT_SCAN_INFO __user *)arg;
- if (get_user(freq_khz, &argp->freq_khz))
- return -EFAULT;
- if (get_user(subch_id, &argp->subch_id))
- return -EFAULT;
- if (get_user(svc_type, &argp->svc_type))
- return -EFAULT;
- if (get_user(bw, &argp->bandwidth))
- return -EFAULT;
- if (!((1<<svc_type) & ISDBT_VALID_SVC_MASK)) {
- DMBERR("Invaild service type: %d\n", svc_type);
- mtv222_cb_ptr->cfged_svc = RTV_SERVICE_INVALID;
- return -EINVAL;
- }
- #if defined(RTV_IF_SPI)
- intr_size = mtv222_cb_ptr->intr_size;
- #else
- intr_size = 0;
- #endif
- mtv222_cb_ptr->cfged_svc = svc_type;
- mtv222_cb_ptr->freq_khz = freq_khz;
- ch_no = RTV_ISDBT_FREQ2CHNUM(mtv222_cb_ptr->country_band_type, freq_khz);
- ret = rtvISDBT_ScanFrequency(ch_no);
- if (ret == RTV_SUCCESS)
- return 0;
- else {
- if(ret != RTV_CHANNEL_NOT_DETECTED)
- DMBERR("Device error: %d\n", ret);
- /* Copy the tuner error-code to application */
- if (put_user(ret, &argp->tuner_err_code))
- return -EFAULT;
- return -EINVAL;
- }
- }
- static INLINE int mtv222_disable_ts_out(void)
- {
- int ret = 0;
- DMBMSG("Enter\n");
- if (!mtv222_cb_ptr->tsout_enabled) {
- DMBMSG("Already TS out Disabled\n");
- return 0;
- }
- mtv222_cb_ptr->tsout_enabled = false;
- rtvISDBT_DisableStreamOut();
- #ifdef _MTV_KERNEL_FILE_DUMP_ENABLE
- mtv_ts_dump_kfile_close();
- #endif
- DMBMSG("Leave\n");
- return ret;
- }
- static INLINE int mtv222_enable_ts_out(void)
- {
- int ret = 0;
- #if defined(RTV_IF_SPI) || defined(RTV_IF_CSI656_RAW_8BIT_ENABLE)
- struct TSB_CB_INFO *tsb_cb = &mtv222_cb_ptr->tsb_cb;
- #endif
- //DMBMSG("ENTER\n");
- if (mtv222_cb_ptr->tsout_enabled) {
- DMBMSG("Already TS out Enabled\n");
- return 0;
- }
- RESET_DEBUG_INTR_STAT;
- RESET_DEBUG_TSPB_STAT;
- if (!((1<<mtv222_cb_ptr->cfged_svc) & ISDBT_VALID_SVC_MASK)) {
- DMBERR("Invaild configured service type: %d\n",
- mtv222_cb_ptr->cfged_svc);
- mtv222_cb_ptr->cfged_svc = RTV_SERVICE_INVALID;
- return -EINVAL;
- }
- #if defined(RTV_IF_SPI) || defined(RTV_IF_CSI656_RAW_8BIT_ENABLE)
- /* Setup the tsb_cb stuff to process interrupt. */
- tsb_cb->avail_seg_idx = 0;
- tsb_cb->avail_write_tspb_idx = 0;
- tsb_cb->enqueue_seg_idx = 0;
- if (mtv222_cb_ptr->intr_size
- != mtv222_cb_ptr->cfged_tsp_chunk_size) {
- mtv222_cb_ptr->cfged_tsp_chunk_size
- = mtv222_cb_ptr->intr_size;
- tsb_cb->num_tsp_per_seg
- = mtv222_cb_ptr->intr_size
- / RTV_TSP_XFER_SIZE;
- tsb_cb->num_total_tsp
- = tsb_cb->num_tsp_per_seg * tsb_cb->num_total_seg;
- }
- DMBMSG("svc_type(%d), #tsp_per_seg(%u), #seg(%u), #total_tsp(%u)\n",
- mtv222_cb_ptr->cfged_svc, tsb_cb->num_tsp_per_seg,
- tsb_cb->num_total_seg, tsb_cb->num_total_tsp);
- #endif
- #ifdef _MTV_KERNEL_FILE_DUMP_ENABLE
- ret = mtv_ts_dump_kfile_open(mtv222_cb_ptr->freq_khz);
- if (ret != 0)
- return ret;
- #endif
- mtv222_cb_ptr->tsout_enabled = true;
- rtvISDBT_EnableStreamOut();
- //DMBMSG("END\n");
- return ret;
- }
- static long mtv222_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- {
- int ret = 0;
- mutex_lock(&mtv222_cb_ptr->ioctl_lock);
-
- switch (cmd) {
- case IOCTL_ISDBT_POWER_ON:
- ret = isdbt_power_on(arg);
- //ret = mtv222_power_on(arg);
- if (ret)
- isdbt_power_off();
- break;
- case IOCTL_ISDBT_POWER_OFF:
- mtv222_disable_ts_out();
- isdbt_power_off();
- break;
- case IOCTL_ISDBT_SCAN_CHANNEL:
- ret = mtv222_scan_channel(arg);
- break;
-
- case IOCTL_ISDBT_SET_CHANNEL:
- ret = mtv222_set_channel(arg);
- break;
- case IOCTL_ISDBT_START_TS:
- ret = mtv222_enable_ts_out();
- break;
- case IOCTL_ISDBT_STOP_TS:
- mtv222_disable_ts_out();
- break;
- case IOCTL_ISDBT_GET_LOCK_STATUS:
- ret = mtv222_get_lock_status(arg);
- break;
- case IOCTL_ISDBT_GET_SIGNAL_INFO:
- ret = mtv222_get_signal_info(arg);
- break;
- case IOCTL_ISDBT_SUSPEND:
- mtv222_enable_standby_mode(arg);
- break;
- case IOCTL_ISDBT_RESUME:
- mtv222_disable_standby_mode(arg);
- break;
- case IOCTL_ISDBT_GET_BER_PER_INFO:
- ret = mtv222_get_ber_per_info(arg);
- break;
- case IOCTL_ISDBT_GET_RSSI:
- ret = mtv222_get_rssi(arg);
- break;
- case IOCTL_ISDBT_GET_CNR:
- ret = mtv222_get_cnr(arg);
- break;
- case IOCTL_ISDBT_GET_SIGNAL_QUAL_INFO:
- ret = mtv222_get_signal_qual_info(arg);
- break;
- /* Test IO command */
- case IOCTL_TEST_GPIO_SET:
- case IOCTL_TEST_GPIO_GET:
- ret = test_gpio(arg, cmd);
- break;
- case IOCTL_TEST_MTV_POWER_ON:
- case IOCTL_TEST_MTV_POWER_OFF:
- test_power_on_off(cmd);
- break;
- case IOCTL_TEST_REG_SINGLE_READ:
- case IOCTL_TEST_REG_BURST_READ:
- case IOCTL_TEST_REG_WRITE:
- case IOCTL_TEST_REG_SPI_MEM_READ:
- case IOCTL_TEST_REG_ONLY_SPI_MEM_READ:
- ret = test_register_io(arg, cmd);
- break;
-
- default:
- DMBERR("Invalid ioctl command: 0x%X\n", cmd);
- ret = -ENOIOCTLCMD;
- break;
- }
- mutex_unlock(&mtv222_cb_ptr->ioctl_lock);
- return ret;
- }
- irqreturn_t mtv222_irq_handler(int irq, void *param)
- {
- U8 *tspb = NULL; /* reset */
- UINT intr_size;
- U8 istatus;
- if (mtv222_cb_ptr->tsout_enabled == false) {
- return IRQ_HANDLED;
- }
- /*
- ¸¸¾à óÀ½À̸é
- #ifdef SCHED_FIFO_USE
- struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
- sched_setscheduler(current, SCHED_FIFO, ¶m);
- #else
- set_user_nice(current, -20);
- #endif
- */
- RTV_GUARD_LOCK;
- rtv_UpdateAdj();
- RTV_REG_MAP_SEL(SPI_CTRL_PAGE);
- intr_size = mtv222_cb_ptr->intr_size;
- /* Read the register of interrupt status. */
- istatus = RTV_REG_GET(0x10);
- //DMBMSG("$$istatus(0x%02X)\n", istatus);
- if (istatus & SPI_UNDERFLOW_INTR) {
- RTV_REG_SET(0x2A, 1);
- RTV_REG_SET(0x2A, 0);
- DMBMSG("UDF: 0x%02X\n", istatus);
- goto exit_isr;
- }
- if (istatus & (SPI_THRESHOLD_INTR|SPI_OVERFLOW_INTR)) {
- /* Allocate a TS buffer from shared memory. */
- tspb = tsb_get();
- if (tspb) {
- RTV_REG_MAP_SEL(SPI_MEM_PAGE);
- RTV_REG_BURST_GET(0x10, tspb, intr_size);
- #ifdef _MTV_KERNEL_FILE_DUMP_ENABLE
- mtv_ts_dump_kfile_write(tspb, intr_size);
- #endif
- #if 0
- {
- UINT i;
- const U8 *tspb = (const U8 *)tspb;
-
- for (i = 0; i < size/188; i++, tsp_buf_ptr += 188) {
- DMBMSG("[%d] 0x%02X 0x%02X 0x%02X 0x%02X | 0x%02X\n",
- i, tsp_buf_ptr[0], tsp_buf_ptr[1],
- tsp_buf_ptr[2], tsp_buf_ptr[3],
- tsp_buf_ptr[187]);
- }
- }
- #endif
-
- /* Enqueue */
- tsb_enqueue(tspb);
- DMB_LEVEL_INTR_INC;
- if (istatus & SPI_OVERFLOW_INTR) {
- DMB_OVF_INTR_INC;
- DMBMSG("OVF: 0x%02X\n", istatus);
- }
- } else {
- RTV_REG_SET(0x2A, 1); /* SRAM init */
- RTV_REG_SET(0x2A, 0);
- #ifdef DEBUG_TSP_BUF
- mtv222_cb_ptr->alloc_tspb_err_cnt++;
- #endif
- DMBERR("No more TSP buffer from pool.\n");
- }
- } else
- DMBMSG("No data interrupt (0x%02X)\n", istatus);
-
- exit_isr:
- RTV_GUARD_FREE;
- return IRQ_HANDLED;
- }
- static int mtv222_remove(void)
- {
- mutex_lock(&mtv222_cb_ptr->ioctl_lock);
- mtv222_power_off();
- mutex_unlock(&mtv222_cb_ptr->ioctl_lock);
- mutex_destroy(&mtv222_cb_ptr->ioctl_lock);
- tsb_free_mapping_area();
- if (mtv222_cb_ptr) {
- kfree(mtv222_cb_ptr);
- mtv222_cb_ptr = NULL;
- }
- return 0;
- }
- static int mtv222_probe(void)
- {
- int ret;
- mtv222_cb_ptr = kzalloc(sizeof(struct MTV222_CB), GFP_KERNEL);
- if (!mtv222_cb_ptr) {
- DMBERR("MTV222 CB allocating error!\n");
- return false;
- }
- ret = tsb_alloc_mapping_area(MAX_TSB_DESC_SIZE, MAX_TSB_SEG_SIZE,
- MAX_NUM_TSB_SEG);
- if (ret) {
- kfree(mtv222_cb_ptr);
- mtv222_cb_ptr = NULL;
- return ret;
- }
- mutex_init(&mtv222_cb_ptr->ioctl_lock);
- return ret;
- }
- static struct isdbt_drv_func raontech_mtv222_drv_func = {
- .probe = mtv222_probe,
- .remove = mtv222_remove,
- .power_on = mtv222_power_on,
- .power_off = mtv222_power_off,
- .mmap = mtv222_mmap,
- .ioctl = mtv222_ioctl,
- .irq_handler = mtv222_irq_handler,
- };
- struct isdbt_drv_func *mtv222_drv_func(void)
- {
- DMBMSG("isdbt_drv_func : mtv222\n");
- return &raontech_mtv222_drv_func;
- }
|