/*************************************************************************** * Copyright (c) 2008, Broadcom Corporation * All Rights Reserved * Confidential Property of Broadcom Corporation * * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. * * $brcm_Workfile: $ * $brcm_Revision: $ * $brcm_Date: $ * * Module Description: * * Revision History: * * $brcm_Log: $ * ***************************************************************************/ #include "scte_127.h" #include "pes_scte_127.h" #include "bapp_amol.h" #include "bapp_gs.h" #include "bstd.h" #include "bkni.h" #include "ministd.h" #include "gist.h" #include "bvbi_chip_priv.h" #if (BVBI_P_NUM_GSE >= 1) #include "bchp_gse_0.h" /* RDB info for primary Gemstar encoder core */ #endif #if (BVBI_P_NUM_GSE >= 2) #include "bchp_gse_1.h" /* RDB info for secondary Gemstar encoder core */ #endif #if (BVBI_P_NUM_GSE >= 3) #include "bchp_gse_2.h" /* RDB info for tertiary Gemstar encoder core */ #endif #if (BVBI_P_NUM_GSE_656 >= 1) #include "bchp_gse_ancil_0.h" /* RDB info for bypass Gemstar encoder core */ #endif #ifndef USE_LEGACY_AMOL_GS /* to use VBI lib functions instead */ #include "bsettop_display.h" /*#include "bvbi.h"*/ #endif BDBG_MODULE(scte_127); #ifndef SCTE_ASSERT #define SCTE_ASSERT(expr) { \ if (!expr) \ printf("%s failed at %s:%d\n",#expr, __FILE__, __LINE__); \ } #endif #define SCTE_127_MUTEX_TIMEOUT (g_ticks_per_second * 2) #ifdef USE_LEGACY_AMOL_GS static bapp_amol_t g_p_amol = NULL; /* pointer to amol encoder object */ static bapp_gs_t g_p_gs = NULL; /* pointer to Gemstar (TVG2X) encoder object */ #endif static pscte_127_handle s_pscte_127 = NULL; /* * This function is used to return scte 127 handle * * Parameters: * NONE * * Returns: * pointer to scte_127_handle if success */ pscte_127_handle scte_127_get_handle(void) { return s_pscte_127; } /* * This function is used to initialize scte 127 object * * Parameters: * NONE * * Returns: * pointer to scte_127_handle if success * NULL otherwise */ pscte_127_handle scte_127_init(void) { pscte_127_handle pscte_127; pscte_127_data pdata; int i; BDBG_MSG(("%s: enter", __func__)); pscte_127 = (pscte_127_handle)malloc(sizeof(scte_127_handle)); if (NULL == pscte_127) { BDBG_ERR(("%s: no memory", __func__)); return NULL; } memset(pscte_127, 0, sizeof(scte_127_handle)); for (i = 0; i < SCTE_127_MAX_FIELD; i++) { initl(&pscte_127->amol_list[i]); initl(&pscte_127->gs_list[i]); } initl(&pscte_127->free_list); /* put all buffer in free list */ for (i = 0; i < SCTE_127_NUM_DATA_BUF; i++) { pdata = &(pscte_127->data[i]); inslt(&(pscte_127->free_list), pdata); } #ifdef USE_LEGACY_AMOL_GS /* no AMOL for PAL */ #if (DISPLAY_NTSC == 1) g_p_amol = bapp_amol_open(NULL); if (!g_p_amol) { scte_127_deinit(pscte_127); BDBG_ERR(("%s: open AMOL module failed", __func__)); return NULL; } #endif g_p_gs = bapp_gs_open(NULL); if (!g_p_gs) { scte_127_deinit(pscte_127); BDBG_ERR(("%s: open GemStar module failed", __func__)); return NULL; } #if (DISPLAY_NTSC == 1) bapp_amol_enable(g_p_amol, 1); /* enable AMOL */ #endif bapp_gs_enable(g_p_gs, 1); /* enable GemStar */ #endif BDBG_MSG(("%s: leave", __func__)); s_pscte_127 = pscte_127; return pscte_127; } /* * This function is used to de-initialize scte 127 object initialize before * * Parameters: * pointer to scte 127 handle * * Returns: * NONE */ void scte_127_deinit(pscte_127_handle pscte_127) { BDBG_MSG(("%s: enter", __func__)); if (!pscte_127) { BDBG_MSG(("%s: null pointer", __func__)); return; } #ifdef USE_LEGACY_AMOL_GS if (g_p_amol) { bapp_amol_enable(g_p_amol, 0); /* diable AMOL */ bapp_amol_close(g_p_amol); g_p_amol = NULL; } if (g_p_gs) { bapp_gs_enable(g_p_gs, 0); /* diable GemStar */ bapp_gs_close(g_p_gs); g_p_gs = NULL; } #endif free(pscte_127); BDBG_MSG(("%s: leave", __func__)); } /* will use a new fast swap when necessary */ void scte_bit_swap(unsigned char *pbuf, int size) { unsigned char c, c1, i; while (size) { c1 = 0; c = *pbuf; for (i = 0; i < 7; i++) { c1 |= (c & 0x1); c = c >> 1; c1 = c1 << 1; } c1 |= (c & 0x1); *pbuf++ = c1; size--; } } /* * parsing pes data field of giving packet for a data unit block * * Parameters: * packet[in] pointer to the data unit of PES packet * size[in] length of data buffer * data[out] pointer to scte_127_data structure for holding the data * unit_type[out] pointer for holding date unit type if found * * Returns: * number of bytes consumed * 0 if no data is found */ int scte_pes_data_field(unsigned char *packet, int size, scte_127_data *data, int *unit_type) { int bytes = 0, data_unit_id, data_unit_length; unsigned char *buf = packet; BDBG_MSG(("%s: enter", __func__)); if (!packet || size < (SCTE_127_DATA_UNIT_ID_CP_LEN + 2) || !data || !unit_type) { BDBG_ERR(("%s: invalid parameter", __func__)); return 0; } data_unit_id = buf[0]; data_unit_length = buf[1]; switch (data_unit_id) { case SCTE_127_DATA_UNIT_ID_AMOL48: if ((size - 2) >= SCTE_127_DATA_UNIT_ID_AMOL48_LEN) { /* skip data field header */ bytes += 2; /* data unit header */ data->field_parity = SCTE_127_DATA_UNIT_FIELD_PARITY(buf[bytes]); data->line_offset = SCTE_127_DATA_UNIT_LINE_OFFSET(buf[bytes]); if (!(data->line_offset >= 10 && data->line_offset <= 22)) BDBG_WRN(("%s: invalid line %d", __func__, data->line_offset)); bytes++; data->u.amol48[0] = AMOL_SOM_48 | (buf[bytes] & 0x80); bytes++; data->u.amol48[1] = (buf[bytes - 1] & 0x7f) | (buf[bytes] & 0x80); bytes++; data->u.amol48[2] = (buf[bytes - 1] & 0x7f) | (buf[bytes] & 0x80); bytes++; data->u.amol48[3] = (buf[bytes - 1] & 0x7f) | (buf[bytes] & 0x80); bytes++; data->u.amol48[4] = (buf[bytes - 1] & 0x7f) | (buf[bytes] & 0x80); bytes++; data->u.amol48[5] = (buf[bytes - 1] & 0x7f) | (buf[bytes] & 0x80); bytes++; data->u.amol48[6] = 0; data->u.amol48[7] = 0; data->u.amol48[8] = 0; data->u.amol48[9] = 0; data->u.amol48[10] = 0; data->u.amol48[11] = 0; data->u.amol48[12] = 0; *unit_type = data_unit_id; return bytes; } break; case SCTE_127_DATA_UNIT_ID_AMOL96: if ((size - 2) >= SCTE_127_DATA_UNIT_ID_AMOL96_LEN) { /* skip data field header */ bytes += 2; /* data unit header */ data->field_parity = SCTE_127_DATA_UNIT_FIELD_PARITY(buf[bytes]); data->line_offset = SCTE_127_DATA_UNIT_LINE_OFFSET(buf[bytes]); if (!(data->line_offset >= 10 && data->line_offset <= 22)) BDBG_WRN(("%s: invalid line %d", __func__, data->line_offset)); bytes++; data->u.amol96[ 0] = AMOL_SOM_96; data->u.amol96[ 1] = buf[bytes]; bytes++; data->u.amol96[ 2] = buf[bytes]; bytes++; data->u.amol96[ 3] = buf[bytes]; bytes++; data->u.amol96[ 4] = buf[bytes]; bytes++; data->u.amol96[ 5] = buf[bytes]; bytes++; data->u.amol96[ 6] = buf[bytes]; bytes++; data->u.amol96[ 7] = buf[bytes]; bytes++; data->u.amol96[ 8] = buf[bytes]; bytes++; data->u.amol96[ 9] = buf[bytes]; bytes++; data->u.amol96[10] = buf[bytes]; bytes++; data->u.amol96[11] = buf[bytes]; bytes++; *unit_type = data_unit_id; return bytes; } break; #ifdef SCTE_127_NABTS case SCTE_127_DATA_UNIT_ID_NABTS: if ((size - 2) >= SCTE_127_DATA_UNIT_ID_NABTS_LEN) { unsigned char framing_code; /* skip data field header */ bytes += 2; /* data unit header */ data->field_parity = SCTE_127_DATA_UNIT_FIELD_PARITY(buf[bytes]); data->line_offset = SCTE_127_DATA_UNIT_LINE_OFFSET(buf[bytes]); if (!(data->line_offset >= 10 && data->line_offset <= 22)) BDBG_WRN(("%s: invalid line %d", __func__, data->line_offset)); bytes++; framing_code = SCTE_127_DATA_UNIT_LINE_OFFSET(buf[bytes]); bytes++; //SCTE_ASSERT(SCTE_127_DATA_NABTS_FRAMING_CODE == framing_code); BKNI_Memcpy(data->u.nabts, &buf[bytes], SCTE_127_DATA_UNIT_ID_NABTS_LEN - 2); bytes += SCTE_127_DATA_UNIT_ID_NABTS_LEN - 2; *unit_type = data_unit_id; return bytes; } break; #endif case SCTE_127_DATA_UNIT_ID_TVG2X: if ((size - 2) >= SCTE_127_DATA_UNIT_ID_TVG2X_LEN) { /* skip data field header */ bytes += 2; /* data unit header */ data->field_parity = SCTE_127_DATA_UNIT_FIELD_PARITY(buf[bytes]); data->line_offset = SCTE_127_DATA_UNIT_LINE_OFFSET(buf[bytes]); if (!(data->line_offset >= 10 && data->line_offset <= 22)) BDBG_WRN(("%s: invalid line %d", __func__, data->line_offset)); bytes++; /* RLQ, to make sure the byte order to match byte_swap_video_sample setting */ data->u.tvg2x = (uint32_t)((buf[bytes] << 24) + (buf[bytes + 1] << 16) + (buf[bytes + 2] << 8) + buf[bytes + 3]); //data->u.tvg2x = (uint32_t)(buf[bytes] + (buf[bytes + 1] << 8) + // (buf[bytes + 2] << 16) + (buf[bytes + 3] << 24)); bytes += SCTE_127_DATA_UNIT_ID_TVG2X_LEN - 1; *unit_type = data_unit_id; return bytes; } break; case SCTE_127_DATA_UNIT_ID_VITC: if ((size - 2) >= SCTE_127_DATA_UNIT_ID_VITC_LEN) { /* skip data field header */ bytes += 2; /* data unit header */ data->field_parity = SCTE_127_DATA_UNIT_FIELD_PARITY(buf[bytes]); data->line_offset = SCTE_127_DATA_UNIT_LINE_OFFSET(buf[bytes]); if (!(data->line_offset >= 14 && data->line_offset <= 22)) BDBG_WRN(("%s: invalid line %d", __func__, data->line_offset)); bytes++; BKNI_Memcpy(data->u.vitc, &buf[bytes], SCTE_127_DATA_UNIT_ID_VITC_LEN - 1); bytes += SCTE_127_DATA_UNIT_ID_VITC_LEN - 1; *unit_type = data_unit_id; return bytes; } break; case SCTE_127_DATA_UNIT_ID_CP: if ((size - 2) >= SCTE_127_DATA_UNIT_ID_CP_LEN) { /* skip data field header */ bytes += 2; /* data unit header */ data->field_parity = SCTE_127_DATA_UNIT_FIELD_PARITY(buf[bytes]); data->line_offset = SCTE_127_DATA_UNIT_LINE_OFFSET(buf[bytes]); bytes++; data->u.cp[0] = buf[bytes]; bytes++; *unit_type = data_unit_id; return bytes; } break; default: BDBG_WRN(("%s: unsupported data unit id (0x%02x)", __func__, data_unit_id)); return 0; } BDBG_MSG(("%s: leave", __func__)); return 0; } /* * go through pes data field block of giving packet for data units * * Parameters: * pscte_127[in] pointer to scte_127 handle * packet[in] pointer to the data unit id of PES packet * size[in] length of data packet * * Returns: * 1 if success * 0 if no data is found or error */ int scte_127_pes_data_field_parser(pscte_127_handle pscte_127, unsigned char *pdata_id, int size) { unsigned int flags; scte_127_data *data; int unit_type; uint8_t *p; int len = 0; uint16_t term; BDBG_MSG(("%s: enter", __func__)); SCTE_ASSERT(pscte_127 && pdata_id && size); if (SCTE_127_DATA_ID != *pdata_id) { BDBG_ERR(("%s: invalid data id (0x%2x)", __func__, *pdata_id)); return 0; } p = (uint8_t *)pdata_id; p++; /* skip data unit id */ size--; do { switch ((int)*p) { default: term = TS_READ_16(p) & 0xff00; if ((0xff00 == term) || (0xffff == term)) { /* terminator, normal */ BDBG_MSG(("%s: terminated\n", __func__)); return 1; } return 0; case SCTE_127_DATA_UNIT_ID_AMOL48: len = (int)*(p + 1); if (len != SCTE_127_DATA_UNIT_ID_AMOL48_LEN) { /* wrong data unit, quit */ BDBG_ERR(("%s: invalid AMOL48 data unit size (%d)\n", __func__, len)); return 0; } break; case SCTE_127_DATA_UNIT_ID_AMOL96: len = (int)*(p + 1); if (len != SCTE_127_DATA_UNIT_ID_AMOL96_LEN) { /* wrong data unit, quit */ BDBG_ERR(("%s: invalid AMOL96 data unit size (%d)\n", __func__, len)); return 0; } break; case SCTE_127_DATA_UNIT_ID_TVG2X: len = (int)*(p + 1); if (len != SCTE_127_DATA_UNIT_ID_TVG2X_LEN) { /* wrong data unit, quit */ BDBG_ERR(("%s: invalid TVG2X data unit size (%d)\n", __func__, len)); return 0; } break; } /* get data buffer from free pool */ flags = bos_enter_critical(); data = (pscte_127_data)remlh(&(pscte_127->free_list)); bos_exit_critical(flags); if (data) { if (scte_pes_data_field(p, size, data, &unit_type)) { data->data_unit_type = unit_type; /* specific to AMOL */ if (SCTE_127_DATA_UNIT_ID_AMOL48 == unit_type) data->amol_type = AMOL_TYPE_I; else if (SCTE_127_DATA_UNIT_ID_AMOL96 == unit_type) data->amol_type = AMOL_TYPE_II_1M; if (!scte_127_queue_data(pscte_127, data)) { BDBG_WRN(("%s: scte_127_queue_data failed", __func__)); /* put buffer back to free list */ scte_127_queue_buffer(pscte_127, data); return 0; } } else { BDBG_ERR(("%s: invalid pes data field", __func__)); /* put buffer back to free list */ scte_127_queue_buffer(pscte_127, data); return 0; } } else { BDBG_WRN(("%s: no free data buffer\n", __func__)); /* reset buffer */ scte_127_reset(pscte_127); return 0; } p += (len + 1) + 1; size -= ((len + 1) + 1); } while ((size - 2) > 0); BDBG_MSG(("%s: leave", __func__)); return 1; } /* * To queue given data to list. This function should be called from within SCTE 127 * data extraction thread. * * Parameters: * pscte_127 pointer to scte_127 handle * pdata pointer to scte_127_data structure to queue * * Returns: * 1 if success * 0 otherwise */ int scte_127_queue_data(pscte_127_handle pscte_127, pscte_127_data pdata) { unsigned int flags; BDBG_MSG(("%s: enter", __func__)); if (!pscte_127 || !pdata) { BDBG_ERR(("%s: NULL pointer", __func__)); return 0; } /* validation, and drop invalidated data early */ if (!(0 == pdata->field_parity || 1 == pdata->field_parity)) { BDBG_ERR(("%s: invalid field parity %d", __func__, pdata->field_parity)); return 0; } switch (pdata->data_unit_type) { /* currently we support following data type */ case SCTE_127_DATA_UNIT_ID_AMOL48: case SCTE_127_DATA_UNIT_ID_AMOL96: /* validation, and drop invalidated data early */ if (20 != pdata->line_offset && 22 != pdata->line_offset) { BDBG_WRN(("%s: invalid line offset, drop", __func__)); return 0; } #if (DISPLAY_PAL == 1) || (DISPLAY_PAL_NC == 1) /* no AMOL for PAL, so drop it */ return 1; #endif flags = bos_enter_critical(); /* AMOL should be in pdata->u.amol48/96 */ inslt(&(pscte_127->amol_list[pdata->field_parity]), pdata); pscte_127->amol_count[pdata->field_parity]++; bos_exit_critical(flags); break; case SCTE_127_DATA_UNIT_ID_TVG2X: /* validation, and drop invalidated data early */ if (pdata->line_offset < 10 || pdata->line_offset > 22) { BDBG_WRN(("%s: invalid line offset, drop", __func__)); return 0; } flags = bos_enter_critical(); /* GS should be in pdata->u.tvg2x */ inslt(&(pscte_127->gs_list[pdata->field_parity]), pdata); pscte_127->gs_count[pdata->field_parity]++; bos_exit_critical(flags); break; default: BDBG_ERR(("%s: not supported data type 0x%2x", __func__, pdata->data_unit_type)); return 0; } BDBG_MSG(("%s: leave", __func__)); return 1; } /* * to put buffer back to free list. * * Parameters: * pscte_127 pointer to scte_127 handle * pdata pointer to scte_127_data structure to free list * * Returns: * 1 if success * 0 otherwise */ int scte_127_queue_buffer(pscte_127_handle pscte_127, pscte_127_data pdata) { unsigned int flags; BDBG_MSG(("%s: enter", __func__)); #ifdef DEBUG if (!pscte_127 || !pdata) { BDBG_ERR(("%s: NULL pointer", __func__)); return 0; } #endif flags = bos_enter_critical(); /* the real data from SCTE 127, e.g. AMOL should be in pdata->u.amol48/96 already */ inslt(&(pscte_127->free_list), pdata); bos_exit_critical(flags); BDBG_MSG(("%s: leave", __func__)); return 1; } /* * This function is used to check if there are any scte 127 data in the lists * * Parameters: * pscte_127 pointer to scte_127 handle * * Returns: * count of data (AMOL + GS in both even and odd field lists) * 0 otherwise */ int scte_127_has_data(pscte_127_handle pscte_127, int parity) { if (parity < 0 || parity > 1) return 0; return (pscte_127->amol_count[parity] + pscte_127->gs_count[parity]); } /* * This function is used to reset scte 127, clear list. e.g. Used after channel change. * * Parameters: * pscte_127 pointer to scte_127 handle * * Returns: * 1 if success * 0 otherwise */ int scte_127_reset(pscte_127_handle pscte_127) { pscte_127_data pdata; unsigned int flags; int i; BDBG_MSG(("%s: enter", __func__)); if (NULL == pscte_127) { BDBG_WRN(("%s: null pointer", __func__)); return 0; } /* if no data in the lists, simply return */ if ((0 == (scte_127_has_data(pscte_127, 0)) && (0 == scte_127_has_data(pscte_127, 1)))) return 1; flags = bos_enter_critical(); initl(&pscte_127->amol_list[0]); initl(&pscte_127->amol_list[1]); initl(&pscte_127->gs_list[0]); initl(&pscte_127->gs_list[1]); initl(&pscte_127->free_list); pscte_127->amol_count[0] = 0; pscte_127->amol_count[1] = 0; pscte_127->gs_count[0] = 0; pscte_127->gs_count[1] = 0; /* put all buffer in free list */ for (i = 0; i < SCTE_127_NUM_DATA_BUF; i++) { pdata = &(pscte_127->data[i]); inslt(&(pscte_127->free_list), pdata); } bos_exit_critical(flags); BDBG_MSG(("%s: leave", __func__)); return 1; } #ifdef USE_LEGACY_AMOL_GS /* * feed scte 127 data object to corresonding encoder, like AMOL. This function * should be called from within VBI ISR to feed data to SCTE 127 module for * encoding/transcoding. * * Parameters: * pscte_127 pointer to scte_127 handle * parity parity to process * * Returns: * 1 if success * 0 otherwise */ int scte_127_feed_data_buf(pscte_127_handle pscte_127, int parity) { pscte_127_data pdata, pdata_list[SCTE_127_MAX_GS_DATA]; unsigned int flags, amol_pair = 0, gs_count = 0, gs_line = 0, i; BDBG_MSG(("%s: enter", __func__)); #if DEBUG if (!pscte_127) { BDBG_ERR(("%s: NULL pointer", __func__)); return 0; } #endif if (parity < 0 || parity > 1) { BDBG_MSG(("%s: invalid parity", __func__)); return 0; } /* process AMOL data first */ if (pscte_127->amol_count[parity] < 1) { BDBG_MSG(("%s: no AMOL data", __func__)); goto PROCESS_GS; } PROCESS_AMOL: flags = bos_enter_critical(); pdata = (pscte_127_data)remlh(&(pscte_127->amol_list[parity])); if (pdata) pscte_127->amol_count[parity]--; bos_exit_critical(flags); if (!pdata) { /* something wrong? */ BDBG_WRN(("%s: Oops AMOL is wrong", __func__)); goto PROCESS_GS; } if (0 == amol_pair) { /* try next if any */ if (pscte_127->amol_count[parity]) { pdata_list[0] = pdata; amol_pair++; goto PROCESS_AMOL; } /* if only one in the list */ bapp_amol_set_scte_127(g_p_amol, pdata); scte_127_queue_buffer(pscte_127, pdata); amol_pair = 1; } else { /* now check the line offset to make sure they are not same */ if (pdata_list[0]->line_offset >= pdata->line_offset) { /* put back to head of the queue */ flags = bos_enter_critical(); inslh(&(pscte_127->amol_list[parity]), pdata); pscte_127->amol_count[parity]++; bos_exit_critical(flags); bapp_amol_set_scte_127(g_p_amol, pdata_list[0]); scte_127_queue_buffer(pscte_127, pdata_list[0]); } else { bapp_amol_set_scte_127_ex(g_p_amol, pdata_list[0], pdata); flags = bos_enter_critical(); inslt(&(pscte_127->free_list), pdata_list[0]); inslt(&(pscte_127->free_list), pdata); bos_exit_critical(flags); } } PROCESS_GS: /* process GS data */ if (pscte_127->gs_count[parity] < 1) { BDBG_MSG(("%s: no GS data", __func__)); return amol_pair ? 1 : 0; } do { flags = bos_enter_critical(); pdata = (pscte_127_data)remlh(&(pscte_127->gs_list[parity])); if (pdata) pscte_127->gs_count[parity]--; bos_exit_critical(flags); if (!pdata) { BDBG_WRN(("%s: Oops GS is wrong", __func__)); /* something wrong? */ break; } if (gs_count) { if (gs_line >= pdata->line_offset) { /* we are done for this field, put back to head of the queue */ flags = bos_enter_critical(); inslh(&(pscte_127->gs_list[parity]), pdata); pscte_127->gs_count[parity]++; bos_exit_critical(flags); break; } } pdata_list[gs_count] = pdata; /* remember current line */ gs_line = pdata->line_offset; } while (gs_count++ < SCTE_127_MAX_GS_DATA && (pscte_127->gs_count[parity] > 0)); /* process buffer */ bapp_gs_set_scte_127_list(g_p_gs, gs_count, pdata_list); /* release buffer */ flags = bos_enter_critical(); for (i = 0; i < gs_count; i++) { inslt(&(pscte_127->free_list), pdata_list[i]); } bos_exit_critical(flags); BDBG_MSG(("%s: leave", __func__)); return 1; } #else int scte_127_feed_data_buf(pscte_127_handle pscte_127, int parity) { return 0; } #endif #ifdef HAS_VBI /* * set GS active line and base for given parity * * Parameters: * pscte_127 pointer to scte_127 handle * parity parity to set * base base * line_mask mask for given line * * Returns: * 1 if success * 0 otherwise */ int scte_127_set_gs_line_mask(pscte_127_handle pscte_127, int parity, unsigned int base, unsigned int line_mask) { unsigned int regVal; #if (BVBI_P_NUM_GSE >= 1) if (!pscte_127) { BDBG_MSG(("%s: null pointer", __func__)); return 0; } /* currently use GSE 0 only */ if (parity) { regVal = BREG_Read32(GetREG(), BCHP_GSE_0_ACTIVE_LINE_BOT); regVal &= ~(BCHP_MASK(GSE_0_ACTIVE_LINE_BOT, ACTIVE_LINE) | BCHP_MASK(GSE_0_ACTIVE_LINE_BOT, BASE)); regVal |= BCHP_FIELD_DATA(GSE_0_ACTIVE_LINE_BOT, ACTIVE_LINE, line_mask) | BCHP_FIELD_DATA(GSE_0_ACTIVE_LINE_BOT, BASE, base); BREG_Write32(GetREG(), BCHP_GSE_0_ACTIVE_LINE_BOT, regVal + 7); /* GES encoder will adjust by -7 */ } else { regVal = BREG_Read32(GetREG(), BCHP_GSE_0_ACTIVE_LINE_TOP); regVal &= ~(BCHP_MASK(GSE_0_ACTIVE_LINE_TOP, ACTIVE_LINE) | BCHP_MASK(GSE_0_ACTIVE_LINE_TOP, BASE)); regVal |= BCHP_FIELD_DATA(GSE_0_ACTIVE_LINE_TOP, ACTIVE_LINE, line_mask) | BCHP_FIELD_DATA(GSE_0_ACTIVE_LINE_TOP, BASE, base); BREG_Write32(GetREG(), BCHP_GSE_0_ACTIVE_LINE_TOP, regVal); } #endif return 1; } /* * to put buffer back to free list. * * Parameters: * pscte_127 pointer to scte_127 handle * pdata pointer to scte_127_data structure to free list * * Returns: * 1 if success * 0 otherwise */ int scte_127_queue_buffer_isr(pscte_127_handle pscte_127, pscte_127_data pdata) { /* the real data from SCTE 127, e.g. AMOL should be in pdata->u.amol48/96 already */ if (pdata) { inslt(&(pscte_127->free_list), pdata); return 1; } return 0; } pscte_127_data scte_127_get_amol_data_buf_isr(pscte_127_handle pscte_127, int parity) { pscte_127_data pdata = NULL; unsigned int flags; BDBG_MSG(("%s: enter", __func__)); if (parity < 0 || parity > 1) { BDBG_WRN(("%s: invalid parity", __func__)); return NULL; } /* process AMOL data first */ if (pscte_127->amol_count[parity] < 1) { return NULL; } flags = bos_enter_critical(); pdata = (pscte_127_data)remlh(&(pscte_127->amol_list[parity])); if (pdata) pscte_127->amol_count[parity]--; bos_exit_critical(flags); return pdata; } bool scte_127_get_amol_data_buf_isr_ex(pscte_127_handle pscte_127, int parity, int *type, unsigned char *amol_data) { pscte_127_data pdata = NULL, line_offset = 0; unsigned int flags, amol_pair = 0; BDBG_MSG(("%s: enter", __func__)); *type = AMOL_TYPE_NONE; if (parity < 0 || parity > 1) { BDBG_WRN(("%s: invalid parity", __func__)); return false; } /* process AMOL data first */ if (pscte_127->amol_count[parity] < 1) { return false; } PROCESS_AMOL: flags = bos_enter_critical(); pdata = (pscte_127_data)remlh(&(pscte_127->amol_list[parity])); if (pdata) pscte_127->amol_count[parity]--; bos_exit_critical(flags); if (!pdata) { /* something wrong? */ BDBG_WRN(("%s: Oops AMOL is wrong", __func__)); return false; } if (0 == amol_pair) { /* try next if any */ amol_pair++; *type = pdata->amol_type; memcpy(amol_data, pdata->u.amol96, sizeof(pdata->u.amol96)); line_offset = pdata->line_offset; scte_127_queue_buffer(pscte_127, pdata); if (pscte_127->amol_count[parity]) { goto PROCESS_AMOL; } } else { /* now check the line offset to make sure they are not same */ if (line_offset >= pdata->line_offset) { /* put back to head of the queue */ flags = bos_enter_critical(); inslh(&(pscte_127->amol_list[parity]), pdata); pscte_127->amol_count[parity]++; bos_exit_critical(flags); } else { /* force to set AMOL96 high bit rate */ *type = AMOL_TYPE_II_2M; memcpy(&amol_data[12], pdata->u.amol96, sizeof(pdata->u.amol96)); scte_127_queue_buffer(pscte_127, pdata); } } /* we have AMOL data */ return true; } int scte_127_get_gs_data_buf_isr(pscte_127_handle pscte_127, int parity, int *line_offset, int *gs_count, uint32_t *gs_data) { static pscte_127_data pdata = NULL; unsigned int count = 0, gs_line = 0; /* function is called from within ISR routine, so don't need critical section */ if (parity < 0 || parity > 1) { BDBG_MSG(("%s: invalid parity", __func__)); return 0; } /* process GS data */ if (pscte_127->gs_count[parity] < 1) { BDBG_MSG(("%s: no GS data", __func__)); return 0; } do { pdata = (pscte_127_data)remlh(&(pscte_127->gs_list[parity])); if (pdata) pscte_127->gs_count[parity]--; if (!pdata) { BDBG_WRN(("%s: Oops GS is wrong", __func__)); /* something wrong? */ gs_count = 0; return 0; } if (count) { if (gs_line >= pdata->line_offset) { /* we are done for this field, put back to head of the queue */ inslh(&(pscte_127->gs_list[parity]), pdata); pscte_127->gs_count[parity]++; break; } } else { /* start line for GS data */ *line_offset = pdata->line_offset; } gs_data[count] = pdata->u.tvg2x; /* remember current line */ gs_line = pdata->line_offset; inslt(&(pscte_127->free_list), pdata); } while (count++ < SCTE_127_MAX_GS_DATA && (pscte_127->gs_count[parity] > 0)); *gs_count = count; BDBG_MSG(("%s: leave", __func__)); return 1; } #endif /* * enable/disable SCTE 127 (AMOL and GS) * * Parameters: * pscte_127 pointer to scte_127 handle * enable enable/disable SCTE 127 module * * Returns: * NONE */ void scte_127_enable(pscte_127_handle pscte_127, int enable) { #ifdef USE_LEGACY_AMOL_GS #if (DISPLAY_NTSC == 1) bapp_amol_enable(g_p_amol, enable); #endif bapp_gs_enable(g_p_gs, enable); #endif #ifdef HAS_VBI scte_127_reset(pscte_127); bdisplay_vbi_enable_amol_gs(enable); #endif }