diff options
Diffstat (limited to 'drivers/media/tdmb/tcc3170/src/tcc_fic_decoder/tcc_fic_decoder.c')
-rw-r--r-- | drivers/media/tdmb/tcc3170/src/tcc_fic_decoder/tcc_fic_decoder.c | 540 |
1 files changed, 0 insertions, 540 deletions
diff --git a/drivers/media/tdmb/tcc3170/src/tcc_fic_decoder/tcc_fic_decoder.c b/drivers/media/tdmb/tcc3170/src/tcc_fic_decoder/tcc_fic_decoder.c deleted file mode 100644 index 8997c44..0000000 --- a/drivers/media/tdmb/tcc3170/src/tcc_fic_decoder/tcc_fic_decoder.c +++ /dev/null @@ -1,540 +0,0 @@ -/* - * tcc_fic_decoder.c - * - * Author: <linux@telechips.com> - * Description: Telechips broadcast driver - * - * Copyright (c) Telechips, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "tcc_fic_decoder.h" - -/****************************************************************************** -* UEP Table -* +---------------+-----------+-----------------------------------+ -* |Bit rate(4bits)|Protect Lv | SubCh Size(9bits) | -* |---------------|---+---+---|---+---+---+---+---+---+---+---+---| -* | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | -* +---------------+-----------+-----------------------------------+ -* -*******************************************************************************/ -static const unsigned short uep_table[64] = { - 0x0810, 0x0615, 0x0418, 0x021d, 0x0023, 0x1818, 0x161d, 0x1423, - 0x122a, 0x1034, 0x281d, 0x2623, 0x242a, 0x2234, 0x3820, 0x362a, - 0x3430, 0x323a, 0x3046, 0x4828, 0x4634, 0x443a, 0x4246, 0x4054, - 0x5830, 0x563a, 0x5446, 0x5254, 0x5068, 0x683a, 0x6646, 0x6454, - 0x6268, 0x7840, 0x7654, 0x7460, 0x7274, 0x708c, 0x8850, 0x8668, - 0x8474, 0x828c, 0x80a8, 0x9860, 0x9674, 0x948c, 0x92a8, 0x90d0, - 0xa874, 0xa68c, 0xa4a8, 0xa2d0, 0xa0e8, 0xb880, 0xb6a8, 0xb4c0, - 0xb2e8, 0xb118, 0xc8a0, 0xc6d0, 0xc318, 0xd8c0, 0xd518, 0xd1a0 }; - -static struct fic_parser_matadata parser_metadata; -static struct tcc_ensemble_info user_ensbl_info; - -static s32 parsing_fig0(struct fic_parser_matadata *fic_info, - u8 *fig_buff, s32 length) -{ - s32 ret = FICERR_SUCCESS; - u8 extension; - - fic_info->fig_cn = (*fig_buff & 0x80) >> 7; - fic_info->fig_oe0 = (*fig_buff & 0x40) >> 6; - fic_info->fig_pd = (*fig_buff & 0x20) >> 5; - extension = (*fig_buff++ & 0x1f); - - length--; - /* service link FIG */ - if ((extension != 6) && (extension != 21) && (extension != 24)) { - if (fic_info->fig_cn) { - if (fic_info->reconf_stage) { - if (extension > 0) - return FICERR_FIG0_NEXT_FIG; - } else { - return FICERR_FIG0_NEXT_FIG1; - } - } - } - - switch (extension) { - case EXT_00: - ret = fig0_ext00(fic_info, fig_buff, length); - break; - case EXT_01: - ret = fig0_ext01(fic_info, fig_buff, length); - break; - case EXT_02: - ret = fig0_ext02(fic_info, fig_buff, length); - break; - case EXT_03: - ret = fig0_ext03(fic_info, fig_buff, length); - break; - case EXT_04: - ret = fig0_ext04(fic_info, fig_buff, length); - break; - case EXT_05: - ret = fig0_ext05(fic_info, fig_buff, length); - break; - case EXT_08: - ret = fig0_ext08(fic_info, fig_buff, length); - break; - case EXT_13: - ret = fig0_ext13(fic_info, fig_buff, length); - break; - case EXT_17: - ret = fig0_ext17(fic_info, fig_buff, length); - break; - default: - break; - } - return ret; -} - - -static s32 parsing_fig1( - struct fic_parser_matadata *fic_info, - u8 *fig_buff, - s32 length) -{ - s32 ret; - u8 extension, charset; - - fic_info->fig_oe1 = (*fig_buff & 0x08) >> 3; - - if (fic_info->fig_oe1 != 0) - return FICERR_FIG_NODATA; - - charset = (*fig_buff & 0xf0) >> 4; - extension = (*fig_buff++ & 0x07); - length--; - switch (extension) { - case EXT_00: - ret = fig1_ext00(fic_info, fig_buff, length, charset); - break; - case EXT_01: - ret = fig1_ext01(fic_info, fig_buff, length, charset); - break; - case EXT_04: - ret = fig1_ext04(fic_info, fig_buff, length, charset); - break; - case EXT_05: - ret = fig1_ext05(fic_info, fig_buff, length, charset); - break; - case EXT_06: - ret = fig1_ext06(fic_info, fig_buff, length, charset); - default: - break; - } - - return FICERR_SUCCESS; -} - -static u32 fic_channel_updated(void) -{ - u32 i, j; - u32 num_svc, num_svc_comp, num_subch; - - struct fic_parser_matadata *metadata = &parser_metadata; - struct tcc_ensemble *esmbl = &metadata->esmbl_start; - struct tcc_service *svc = metadata->svc_start; - struct tcc_service_comp *svc_comp = metadata->svc_comp_start; - struct tcc_user_app_types *user_app = metadata->user_app_start; - - num_svc = esmbl->num_svc; - num_svc_comp = esmbl->num_svc_comp; - num_subch = esmbl->num_svc_comp; - - if (!num_svc_comp) - return CH_UPDATE_NO_DATA; - - if (!num_subch) - return CH_UPDATE_NO_DATA; - - if (esmbl->label[0] == 0x00) - return CH_UPDATE_NO_DATA; - - if (num_svc) { - for (i = 0; i < num_svc; i++) { - if ((svc + i)->svc_label[0] == 0) - return CH_UPDATE_NO_DATA; - } - } else { - return CH_UPDATE_NO_DATA; - } - - for (i = 0; i < num_svc_comp; i++) { - if ((svc_comp + i)->fidc_id == 0xff) - return CH_UPDATE_NO_DATA; - } - - for (i = 0; i < num_svc_comp; i++) { - if (svc_comp[i].tmid == 3 || svc_comp[i].ascty_dscty == 5) { - if (svc_comp[i].ascty_dscty == 0) - return CH_UPDATE_ESSENTIAL_DATA; - - for (j = 0; j < num_svc_comp; j++) { - if (svc_comp[i].sid == user_app[j].sid && - svc_comp[i].scids == user_app[j].scids) - break; - } - if (j == num_svc_comp) - return CH_UPDATE_ESSENTIAL_DATA; - - if (svc_comp[i].scids == 0x0f) - return CH_UPDATE_ESSENTIAL_DATA; - } - - if (svc_comp[i].order) { - if ((svc_comp + i)->label[0] == 0) - return CH_UPDATE_ESSENTIAL_DATA; - } - } - - return CH_UPDATE_FULL_DATA; -} - -void tcc_fic_parser_init(void) -{ - s32 i; - struct fic_parser_matadata *metadata; - - metadata = &parser_metadata; - memset(metadata, 0, sizeof(parser_metadata)); - - metadata->reconf_stage = 0; - metadata->fig_cn = 0; - metadata->fig_oe0 = 0; - metadata->fig_pd = 0; - metadata->fig_oe1 = 0; - metadata->fib_cnt = 0; - - for (i = 0; i < NUM_SVC_COMP; i++) - metadata->svc_comp_start[i].scids = 0x0f; - - for (i = 0; i < NUM_USER_APP; i++) - metadata->user_app_start[i].scids = 0x0f; -} - -static s32 fib_decode(u8 *fig_buff) -{ - s32 ret = FICERR_SUCCESS; - struct fic_parser_matadata *fic_info; - - s32 fig_len; - u32 fig_type; - u32 buff_point = 0; - s32 buff_len = 30; - - fic_info = &parser_metadata; - - if (ret != FICERR_SUCCESS) - return ret; - - /* the size of FIG is bigger than 2bytes */ - while (buff_len > 0) { - /* find a FIG header */ - if (*(fig_buff + buff_point) == 0xff || - *(fig_buff + buff_point) == 0x00) { - ret = FICERR_FIBD_ENDMARKER; - break; - } - - fig_type = (*(fig_buff + buff_point) & 0xe0) >> 5; - fig_len = (*(fig_buff + buff_point) & 0x1f); - if (fig_len > 29 || fig_len == 0) - return FICERR_FIBD_INVALID_LENGTH; - - buff_point++; - if (fig_len <= 0x01) { - ret = FICERR_FIG_NODATA; - return ret; - } - - switch (fig_type) { - case FIG0: - ret = parsing_fig0(fic_info, - fig_buff + buff_point, fig_len); - break; - case FIG1: - ret = parsing_fig1(fic_info, - fig_buff+buff_point, fig_len); - break; - default: - ret = FICERR_FIBD_UNKNOWN_FIGTYPE; - return ret; - } - - buff_point += fig_len; - buff_len -= (fig_len + 1); - } - - if (buff_len < 0) - ret = FICERR_FIBD_INVALID_LENGTH; - return ret; -} - -static u16 fib_crc16(u8 *buf) -{ - u32 b, len; - u8 crcl, crcm; - - crcl = 0xff; - crcm = 0xff; - - - for (len = 0; len < 30; len++) { - b = *(buf + len) ^ crcm; - b = b ^ (b >> 4); - crcm = crcl ^ (b >> 3) ^ (b << 4); - crcl = b ^ (b << 5); - } - - crcl = crcl ^ 0xff; - crcm = crcm ^ 0xff; - return (u16)crcl | ((u16)crcm << 8); -} - - -static void fic_copy_sub_ch(struct fic_parser_matadata *fic_info, - struct tcc_service_comp_info *svc_comp_info) -{ - s32 i; - struct tcc_ensemble *esbl = &fic_info->esmbl_start; - struct tcc_sub_channel *subch_start = fic_info->subch_start; - - for (i = 0; i < esbl->num_svc_comp; i++) { - if (svc_comp_info->svc_comp.fidc_id != subch_start[i].subch_id) - continue; - memcpy(&svc_comp_info->sub_ch, &subch_start[i], - sizeof(struct tcc_sub_channel)); - break; - } -} - -static void fic_copy_svc_comp(struct fic_parser_matadata *fic_info, - struct tcc_service_info *svc_info) -{ - s32 i, j = 0; - struct tcc_ensemble *esbl = &fic_info->esmbl_start; - struct tcc_service_comp *src_svc_comp = fic_info->svc_comp_start; - struct tcc_service_comp_info *svc_comp_info; - - for (i = 0; i < esbl->num_svc_comp; i++) { - if (svc_info->svc.sid != src_svc_comp[i].sid) - continue; - svc_comp_info = &svc_info->svc_comp_info[j]; - memcpy(&svc_comp_info->svc_comp, &src_svc_comp[i], - sizeof(struct tcc_service_comp)); - fic_copy_sub_ch(fic_info, svc_comp_info); - j++; - } -} - -struct tcc_service_comp_info *tcc_fic_get_svc_comp_info(s32 _subch_id) -{ - s32 i; - struct tcc_service_comp_info *svc_comp_info; - struct tcc_ensemble *ensbl = &user_ensbl_info.ensbl; - struct tcc_service_info *svc_info = user_ensbl_info.svc_info; - - for (i = 0; i < ensbl->num_svc_comp; i++) { - svc_comp_info = &svc_info[i].svc_comp_info[0]; - if (svc_comp_info->svc_comp.fidc_id == _subch_id) - return svc_comp_info; - } - return NULL; -} - -u8 tcc_fic_get_ptype(struct tcc_service_comp_info *svc_comp_info) -{ - struct tcc_sub_channel *sub_ch = &svc_comp_info->sub_ch; - if (sub_ch->form_flag & 0x08) - return 1; - else - return 0; -} - -u8 tcc_fic_get_plevel(struct tcc_service_comp_info *svc_comp_info) -{ - u8 eep8[4] = {0, 1, 2, 3}; - u8 eep32[4] = {4, 5, 6, 7}; - u8 opt, protect; - struct tcc_sub_channel *sub_ch = &svc_comp_info->sub_ch; - - if (sub_ch->form_flag & 0x08) { - opt = (sub_ch->form_flag & 0x04) ? 1 : 0; - protect = sub_ch->form_flag & 0x03; - if (opt) - return eep32[protect]; - else - return eep8[protect]; - } else { - return (uep_table[sub_ch->tbl_index] & 0x0E00) >> 9; - } -} - -u16 tcc_fic_get_cu_size(struct tcc_service_comp_info *svc_comp_info) -{ - struct tcc_sub_channel *sub_ch = &svc_comp_info->sub_ch; - - if (sub_ch->form_flag & 0x08) - return sub_ch->size_cu; - else - return uep_table[sub_ch->tbl_index] & 0x1FF; -} - -u16 tcc_fic_get_cu_start(struct tcc_service_comp_info *svc_comp_info) -{ - struct tcc_sub_channel *sub_ch = &svc_comp_info->sub_ch; - - return sub_ch->size_cu; -} - -u8 tcc_fic_get_subch_id(struct tcc_service_comp_info *svc_comp_info) -{ - struct tcc_sub_channel *sub_ch = &svc_comp_info->sub_ch; - - return sub_ch->subch_id; -} - - -u8 tcc_fic_get_bitrate(struct tcc_service_comp_info *svc_comp_info) -{ - u8 opt, protect; - struct tcc_sub_channel *sub_ch = &svc_comp_info->sub_ch; - - if ((sub_ch->form_flag & 0x08) == 0) - return (uep_table[sub_ch->tbl_index] & 0xf000) >> 12; - - opt = (sub_ch->form_flag & 0x04) ? 1 : 0; - protect = sub_ch->form_flag & 0x03; - if (opt) { - switch (protect) { - case 0: - return sub_ch->size_cu / 27; - case 1: - return sub_ch->size_cu / 21; - case 2: - return sub_ch->size_cu / 18; - case 3: - return sub_ch->size_cu / 15; - default: - return 0; - } - /*human readable bitrate is x32*/ - } else { - switch (protect) { - case 0: - return sub_ch->size_cu / 12; - case 1: - return sub_ch->size_cu / 8; - case 2: - return sub_ch->size_cu / 6; - case 3: - return sub_ch->size_cu / 4; - default: - return 0; - } - /*human readable bitrate is x8*/ - } -} - -u8 tcc_fic_get_rs(struct tcc_service_comp_info *svc_comp_info) -{ - struct tcc_service_comp *svc_comp = &svc_comp_info->svc_comp; - if (svc_comp->ascty_dscty == 0x18) - return 1; - else - return 0; -} - -/** -* @param buff buffer for fic -* @param size fic buffer size. it must be 384 bytes. -* @return -1 : invalid argument, 0 : in progress, > 0 : parsing done -*/ -s32 tcc_fic_run_decoder(u8 *buff, s32 size) -{ - s32 cnt = 0, ret = 0; - s32 num_broken_fib = 0; - u16 fib_crc; - - if ((size%TCC_FIB_SIZE) != 0) { - tcbd_debug(DEBUG_ERROR, "invalid fic size:%d!\n", size); - return -1; - } - while (size > cnt * TCC_FIB_SIZE) { - fib_crc = (u16)(buff[(cnt * TCC_FIB_SIZE) + 30] << 8) | - (u16)buff[(cnt * TCC_FIB_SIZE) + 31]; - if (fib_crc != fib_crc16(buff + (cnt * TCC_FIB_SIZE))) { - num_broken_fib++; - tcbd_debug(DEBUG_ERROR, "broken fib cnt:%d\n", cnt); - goto cont_loop; - } - fib_decode(buff + (cnt * TCC_FIB_SIZE)); - ret = fic_channel_updated(); - if (ret == CH_UPDATE_ESSENTIAL_DATA || - ret == CH_UPDATE_FULL_DATA) { - break; - } -cont_loop: - cnt++; - } - return ret; -} - -void tcc_fic_disp_ensbl_info(struct tcc_ensemble_info *ensbl_info) -{ - s32 i, j; - struct tcc_ensemble *esbl = &ensbl_info->ensbl; - struct tcc_service_info *svc_info; - struct tcc_service_comp_info *svc_comp_info; - - tcbd_debug(DEBUG_INFO, "[ %s ] %d services available!\n", - esbl->label, esbl->num_svc); - for (i = 0; i < esbl->num_svc; i++) { - svc_info = &ensbl_info->svc_info[i]; - tcbd_debug(DEBUG_INFO, " => [ %s ] %d service component\n", - svc_info->svc.svc_label, - svc_info->svc.num_svc_comp); - for (j = 0; j < svc_info->svc.num_svc_comp; j++) { - svc_comp_info = &svc_info->svc_comp_info[j]; - tcbd_debug(DEBUG_INFO, " -> sub channel id [%d]\n", - svc_comp_info[j].svc_comp.fidc_id); - } - } -} - -struct tcc_ensemble_info *tcc_fic_get_ensbl_info(s32 _disp) -{ - s32 i; - struct fic_parser_matadata *fic_info = &parser_metadata; - struct tcc_ensemble *esbl = &fic_info->esmbl_start; - struct tcc_service *svc = fic_info->svc_start; - struct tcc_service_info *svc_info; - - memcpy(&user_ensbl_info.ensbl, esbl, sizeof(struct tcc_ensemble)); - for (i = 0; i < esbl->num_svc; i++) { - svc_info = &user_ensbl_info.svc_info[i]; - memcpy(&svc_info->svc, &svc[i], sizeof(struct tcc_service)); - fic_copy_svc_comp(fic_info, svc_info); - } - - if (_disp) - tcc_fic_disp_ensbl_info(&user_ensbl_info); - - return &user_ensbl_info; -} - |