/*************************************************************************** * 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 "bapp_amol.h" #include "bchp_amole_0.h" #include "bchp_amole_1.h" #include "bchp_vbi_enc.h" #include "bchp_vf_0.h" #include "bstd.h" #include "scte_127.h" #include "ministd.h" #include "gist.h" BDBG_MODULE(bapp_amol); #ifndef AMOL_ASSERT #define AMOL_ASSERT(expr) { \ if (!expr) \ printf("%s failed at %s:%d\n",#expr, __FILE__, __LINE__); \ } #endif #define NUM_AMOL_BUF 4 /* maximux 4 banks, 0 and 2 for top field, 1 and 3 for botton field */ #define AMOL_BUF_SIZE 24 /* maximum data bytes for each field, 6 for AMOL I, 12 for AMOL II@1M, 24 for AMOL II@2M */ #define AMOL_ENABLE_TIMEOUT (g_ticks_per_second * 2) /* * Main data structure containing references to all interfaces * required throughout the application. */ typedef struct _amol_field_buf_t { unsigned int size; unsigned char buf[AMOL_BUF_SIZE]; } amol_field_buf_t; typedef struct _amol_buf_t { unsigned int index; amol_field_buf_t field[NUM_AMOL_BUF]; } amol_buf_t; typedef struct _amol_info_t { AMOL_TYPE type[2]; /* amol type for given lines for a field */ unsigned char line[2]; /* line numbers for a field */ } amol_info_t; struct bapp_amol { bool enabled; b_mutex_t mutex; amol_buf_t buf[NUM_AMOL_BUF]; amol_info_t info[2]; /* for both fields */ unsigned int mask[2]; /* line mask bits for both top and bottom field */ } bapp_amol; bapp_amol_t s_p_amol = NULL; /* Summary: Initialize and allocate resources */ bapp_amol_t bapp_amol_open(void* p_opaque_app) { BDBG_MSG(("%s: enter", __func__)); s_p_amol = (bapp_amol_t)malloc(sizeof(struct bapp_amol)); AMOL_ASSERT(s_p_amol); memset(s_p_amol, 0, sizeof(struct bapp_amol)); AMOL_ASSERT(bos_create_mutex(&s_p_amol->mutex) == b_ok); bapp_amol_init(s_p_amol); BDBG_MSG(("%s: leave", __func__)); return s_p_amol; } /* Summary: Release all resources allocated with bapp_amol_open */ void bapp_amol_close(bapp_amol_t p_amol) { BDBG_WRN(("%s: enter", __func__)); AMOL_ASSERT(p_amol); bos_delete_mutex(&p_amol->mutex); free(p_amol); s_p_amol = NULL; BDBG_WRN(("%s: leave", __func__)); } static void bapp_amol_program_null ( uint32_t ulWritePointer, uint32_t value) { uint32_t ulRegVal = BREG_Read32(GetREG(), BCHP_AMOLE_0_NULL); switch (ulWritePointer & 0x3) { case 1: if (!value) ulRegVal &= ~BCHP_MASK (AMOLE_0_NULL, NULL_ENABLE_BANK1); else ulRegVal |= BCHP_FIELD_DATA (AMOLE_0_NULL, NULL_ENABLE_BANK1, value); break; case 2: if (!value) ulRegVal &= ~BCHP_MASK (AMOLE_0_NULL, NULL_ENABLE_BANK2); else ulRegVal |= BCHP_FIELD_DATA (AMOLE_0_NULL, NULL_ENABLE_BANK2, value); break; case 3: if (!value) ulRegVal &= ~BCHP_MASK (AMOLE_0_NULL, NULL_ENABLE_BANK3); else ulRegVal |= BCHP_FIELD_DATA (AMOLE_0_NULL, NULL_ENABLE_BANK3, value); break; default: case 0: if (!value) ulRegVal &= ~BCHP_MASK (AMOLE_0_NULL, NULL_ENABLE_BANK0); else ulRegVal |= BCHP_FIELD_DATA (AMOLE_0_NULL, NULL_ENABLE_BANK0, value); break; } BREG_Write32(GetREG(), BCHP_AMOLE_0_NULL, ulRegVal); } /* Summary: Enable/Disable AMOL */ void bapp_amol_enable(bapp_amol_t p_amol, bool enable) { uint32_t ulReg, flags; BDBG_MSG(("%s: enter", __func__)); AMOL_ASSERT(p_amol); BDBG_WRN(("%s: enable %d - current %d\n", __func__, enable, p_amol->enabled)); if (bos_acquire_mutex(&(p_amol->mutex), AMOL_ENABLE_TIMEOUT) != b_ok) { BDBG_ERR(("%s bos_acquire_mutex failed(enable = %d)\n",__func__,enable)); return; } #if 0 if (p_amol->enabled == enable) { bos_release_mutex(&(p_amol->mutex)); BDBG_WRN(("%s: no change", __func__)); return; } #endif p_amol->enabled = enable; /* sel 5 for AMOL */ ulReg = BREG_Read32(GetREG(), BCHP_VBI_ENC_VBI_0_CORE_5_SEL); ulReg &= ~BCHP_MASK(VBI_ENC_VBI_0_CORE_5_SEL, SEL); if (enable) { ulReg = BCHP_FIELD_ENUM (VBI_ENC_VBI_0_CORE_5_SEL, SEL, AMOLE_0); } BREG_Write32(GetREG(), BCHP_VBI_ENC_VBI_0_CORE_5_SEL, ulReg); ulReg = BREG_Read32(GetREG(), BCHP_VF_0_MISC); ulReg &= ~BCHP_MASK(VF_0_MISC, VBI_ENABLE); ulReg &= ~BCHP_MASK(VF_0_MISC, VBI_PREFERRED); if (enable) { ulReg |= BCHP_FIELD_ENUM (VF_0_MISC, VBI_ENABLE, ON); ulReg |= BCHP_FIELD_ENUM (VF_0_MISC, VBI_PREFERRED, ON); } BREG_Write32(GetREG(), BCHP_VF_0_MISC, ulReg); bos_release_mutex(&(p_amol->mutex)); flags = bos_enter_critical(); ulReg = BREG_Read32(GetREG(), BCHP_VBI_ENC_VBI_0_INTR_CTRL); ulReg &= !BCHP_MASK(VBI_ENC_VBI_0_INTR_CTRL, INTR0_LINE); if (enable) ulReg = BCHP_FIELD_DATA(VBI_ENC_VBI_0_INTR_CTRL, INTR0_LINE, 20); else ulReg = BCHP_FIELD_DATA(VBI_ENC_VBI_0_INTR_CTRL, INTR0_LINE, 0); BREG_Write32(GetREG(), BCHP_VBI_ENC_VBI_0_INTR_CTRL, ulReg); bos_exit_critical(flags); BDBG_MSG(("%s: leave", __func__)); } bool bapp_amol_mask_lines( bapp_amol_t p_amol, unsigned char field ) { uint32_t ulReg, mask; uint16_t line1, line2; BDBG_MSG(("%s: enter", __func__)); if (field > 1) { BDBG_ERR(("%s: field (%d) out of range", __func__, field)); return 0; } line1 = p_amol->info[field].line[0]; line2 = p_amol->info[field].line[1]; if (line1 < AMOL_LOWER_LINE || line1 > AMOL_UPPER_LINE) { BDBG_WRN(("%s: invalid VBI line1 %d, %d", __func__, line1)); return 0; } if (line2 < AMOL_LOWER_LINE || line2 > AMOL_UPPER_LINE) { BDBG_WRN(("%s: invalid VBI line2 %d, %d", __func__, line2)); return 0; } mask = (1L << (line1 - AMOL_LOWER_LINE)) | (1L << (line2 - AMOL_LOWER_LINE)); ulReg = 0; if (0 == field) { if (mask != p_amol->mask[0]) { ulReg |= BCHP_FIELD_DATA (AMOLE_0_ACT_LINE_BASE_TOP, BASE, AMOL_LOWER_LINE); ulReg |= BCHP_FIELD_DATA (AMOLE_0_ACT_LINE_BASE_TOP, ACTIVE_LINE, mask); BREG_Write32(GetREG(), BCHP_AMOLE_0_ACT_LINE_BASE_TOP, ulReg); p_amol->mask[0] = mask; } } else if (1 == field) { if (mask != p_amol->mask[1]) { ulReg |= BCHP_FIELD_DATA (AMOLE_0_ACT_LINE_BASE_BOT, BASE, 17); ulReg |= BCHP_FIELD_DATA (AMOLE_0_ACT_LINE_BASE_BOT, ACTIVE_LINE, mask); BREG_Write32(GetREG(), BCHP_AMOLE_0_ACT_LINE_BASE_BOT, ulReg); p_amol->mask[1] = mask; } } return 1; } bool bapp_amol_set_symbolrate( bapp_amol_t p_amol, AMOL_TYPE type ) { uint32_t ulReg = 0; uint32_t nbyte_symbol = (AMOL_TYPE_II_2M == type) ? 1 : 0; BDBG_MSG(("%s: enter", __func__)); /* 6 bytes for TYPE I and TYPE II@1M, 12 bytes for TYPE II@2M */ ulReg |= ( BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE22_BANK3, nbyte_symbol) | BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE20_BANK3, nbyte_symbol) | BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE22_BANK2, nbyte_symbol) | BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE20_BANK2, nbyte_symbol) | BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE22_BANK1, nbyte_symbol) | BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE20_BANK1, nbyte_symbol) | BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE22_BANK0, nbyte_symbol) | BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE20_BANK0, nbyte_symbol) ); BREG_Write32(GetREG(), BCHP_AMOLE_0_BYTES_PER_LINE, ulReg); BDBG_MSG(("%s: leave", __func__)); return 0; } bool bapp_amol_init( bapp_amol_t p_amol ) { uint32_t ulReg, i; BDBG_MSG(("%s: enter", __func__)); p_amol->info[0].type[0] = AMOL_TYPE_I; p_amol->info[0].line[0] = 20; p_amol->info[0].type[1] = AMOL_TYPE_I; p_amol->info[0].line[1] = 22; p_amol->info[1].type[0] = AMOL_TYPE_I; p_amol->info[1].line[0] = 20; p_amol->info[1].type[1] = AMOL_TYPE_I; p_amol->info[1].line[1] = 22; bapp_amol_mask_lines(p_amol, 0); bapp_amol_mask_lines(p_amol, 1); /* IRE */ ulReg = 0; ulReg |= ( BCHP_FIELD_DATA (AMOLE_0_GAIN_PED_TOP, GAIN_LINE22, 70) | BCHP_FIELD_DATA (AMOLE_0_GAIN_PED_TOP, GAIN_LINE20, 70) | BCHP_FIELD_ENUM (AMOLE_0_GAIN_PED_TOP, PED_LINE22, DISABLE) | BCHP_FIELD_ENUM (AMOLE_0_GAIN_PED_TOP, PED_LINE20, DISABLE) ); BREG_Write32(GetREG(), BCHP_AMOLE_0_GAIN_PED_TOP, ulReg); ulReg = 0; ulReg |= ( BCHP_FIELD_DATA (AMOLE_0_GAIN_PED_BOT, GAIN_LINE22, 70) | BCHP_FIELD_DATA (AMOLE_0_GAIN_PED_BOT, GAIN_LINE20, 70) | BCHP_FIELD_ENUM (AMOLE_0_GAIN_PED_BOT, PED_LINE22, DISABLE) | BCHP_FIELD_ENUM (AMOLE_0_GAIN_PED_BOT, PED_LINE20, DISABLE) ); BREG_Write32(GetREG(), BCHP_AMOLE_0_GAIN_PED_BOT, ulReg); /* set default symbol rate */ bapp_amol_set_symbolrate(p_amol, AMOL_TYPE_I); ulReg = 0; ulReg |= ( BCHP_FIELD_DATA (AMOLE_0_NULL, NULL_ENABLE_BANK3, 0) | BCHP_FIELD_DATA (AMOLE_0_NULL, NULL_ENABLE_BANK2, 0) | BCHP_FIELD_DATA (AMOLE_0_NULL, NULL_ENABLE_BANK1, 0) | BCHP_FIELD_DATA (AMOLE_0_NULL, NULL_ENABLE_BANK0, 0) | BCHP_FIELD_DATA (AMOLE_0_NULL, CHARACTER, 0) ); BREG_Write32(GetREG(), BCHP_AMOLE_0_NULL, ulReg); ulReg = 0; ulReg |= ( BCHP_FIELD_DATA (AMOLE_0_CONTROL, DELAY_COUNT, 0x6B) | BCHP_FIELD_DATA (AMOLE_0_CONTROL, FIFO_FREEZE, 0) | BCHP_FIELD_DATA (AMOLE_0_CONTROL, NULL_MODE, 1) ); /* enable NULL insertion */ if (p_amol->enabled) ulReg |= BCHP_FIELD_ENUM (AMOLE_0_CONTROL, ENABLE, ON); BREG_Write32(GetREG(), BCHP_AMOLE_0_CONTROL, ulReg); /* clear data registers first */ for (i = 0; i < 6; i++) { BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK0 + i * 4, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK1 + i * 4, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK2 + i * 4, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK3 + i * 4, 0); } BDBG_MSG(("%s: leave", __func__)); return 0; } void bapp_amol_status( bapp_amol_t p_amol ) { uint32_t ulVal; BDBG_MSG(("%s: enter", __func__)); AMOL_ASSERT(p_amol); if (!p_amol) { BDBG_ERR(("%s: null point", __func__)); return; } if (!p_amol->enabled) { BDBG_ERR(("%s: not enabled yet", __func__)); return; } ulVal = BREG_Read32(GetREG(), BCHP_AMOLE_0_STATUS); if (ulVal & BCHP_AMOLE_0_STATUS_FIFO_OVERFLOW_MASK) { BDBG_ERR(("AMOL: FIFO overflow")); } if (ulVal & BCHP_AMOLE_0_STATUS_FIFO_UNDERFLOW_MASK) { BDBG_ERR(("AMOL: FIFO underflow")); } if (ulVal & BCHP_AMOLE_0_STATUS_BANK3_VIDEO_SAMPLE_DATA_MASK) { BDBG_ERR(("AMOL: Bank3 XMIT")); } if (ulVal & BCHP_AMOLE_0_STATUS_BANK2_VIDEO_SAMPLE_DATA_MASK) { BDBG_ERR(("AMOL: Bank2 XMIT")); } if (ulVal & BCHP_AMOLE_0_STATUS_BANK1_VIDEO_SAMPLE_DATA_MASK) { BDBG_ERR(("AMOL: Bank1 XMIT")); } if (ulVal & BCHP_AMOLE_0_STATUS_BANK0_VIDEO_SAMPLE_DATA_MASK) { BDBG_ERR(("AMOL: Bank0 XMIT")); } if (ulVal & BCHP_AMOLE_0_STATUS_BANK3_656_ANCIL_DATA_MASK) { BDBG_ERR(("AMOL: 656 Ancillary Bank3 XMIT")); } if (ulVal & BCHP_AMOLE_0_STATUS_BANK2_656_ANCIL_DATA_MASK) { BDBG_ERR(("AMOL: 656 Ancillary Bank2 XMIT")); } if (ulVal & BCHP_AMOLE_0_STATUS_BANK1_656_ANCIL_DATA_MASK) { BDBG_ERR(("AMOL: 656 Ancillary Bank1 XMIT")); } if (ulVal & BCHP_AMOLE_0_STATUS_BANK0_656_ANCIL_DATA_MASK) { BDBG_ERR(("AMOL: 656 Ancillary Bank0 XMIT")); } /* clear bits */ if (ulVal & (BCHP_AMOLE_0_STATUS_FIFO_OVERFLOW_MASK | BCHP_AMOLE_0_STATUS_FIFO_UNDERFLOW_MASK)) { BDBG_WRN(("%s: clear over/under flow errors", __func__)); ulVal &= ~BCHP_AMOLE_0_STATUS_reserved0_MASK; BREG_Write32(GetREG(), BCHP_AMOLE_0_STATUS, ulVal); } BDBG_MSG(("%s: leave", __func__)); } uint32_t bapp_amol_set_scte_127( bapp_amol_t p_amol, scte_127_data *line_data) { uint32_t ulRegVal, status; uint32_t ulRegAddr = 0; uint32_t ulReadPointer; uint32_t ulWritePointer; uint32_t bankIndex; int totalBytes, i; uint8_t field = 0, *pAMOLData; BDBG_MSG(("%s: enter", __func__)); /* validation */ if (!p_amol || !line_data) { BDBG_WRN(("%s: null data pointer", __func__)); return -1; } /* currently just assume line is for 20 and 22 only */ if (20 != line_data->line_offset && 22 != line_data->line_offset) { BDBG_WRN(("invalid line, drop (l1=%d)", line_data->line_offset)); return -1; } status = BREG_Read32(GetREG(), BCHP_AMOLE_0_STATUS) & ~BCHP_AMOLE_0_STATUS_reserved0_MASK; BREG_Write32(GetREG(), BCHP_AMOLE_0_STATUS, status); /* Get FIFO pointers */ ulRegVal = BREG_Read32(GetREG(), BCHP_AMOLE_0_WRPTR); ulWritePointer = BCHP_GET_FIELD_DATA (ulRegVal, AMOLE_0_WRPTR, VALUE); bankIndex = ulWritePointer & 0x3; ulRegVal = BREG_Read32(GetREG(), BCHP_AMOLE_0_RDPTR); ulReadPointer = BCHP_GET_FIELD_DATA (ulRegVal, AMOLE_0_RDPTR, VALUE); /* Check for FIFO full */ if (((ulReadPointer & 0x3) == bankIndex) && (ulReadPointer != ulWritePointer)) { if (status & (BCHP_AMOLE_0_STATUS_FIFO_OVERFLOW_MASK | BCHP_AMOLE_0_STATUS_FIFO_UNDERFLOW_MASK)) { BDBG_WRN(("OF/UF (idx=%d,W=%d,R=%d,status=0x%08x)", bankIndex, ulReadPointer, ulWritePointer, status)); return -1; } } /* Decide how many bytes to copy */ switch (line_data->amol_type) { case AMOL_TYPE_I: totalBytes = 6; pAMOLData = line_data->u.amol48; break; /* 12 bytes AMOL 96, but not AMOL 48 */ case AMOL_TYPE_II_1M: pAMOLData = line_data->u.amol96; totalBytes = 12; break; default: BDBG_WRN(("%s: unsupported AMOL type %d", __func__, line_data->amol_type)); return -1; } field = line_data->field_parity? 0 : 1; /* Handle field misalignment */ if (((bankIndex == 0) || (bankIndex == 2)) && /* top field */ (AMOL_FIELD_TOP != field)) { BDBG_MSG(("top field misalignment, bankIndex=%d", bankIndex)); bapp_amol_program_null(bankIndex, 1); ++ulWritePointer; bankIndex++; bankIndex %= 4; } else if (((bankIndex == 1) || (bankIndex == 3)) && /* bottom filed */ (AMOL_FIELD_BOT != field)) { BDBG_MSG(("bot field misalignment, bankIndex=%d", bankIndex)); bapp_amol_program_null(bankIndex, 1); ++ulWritePointer; bankIndex++; bankIndex %= 4; } bapp_amol_program_null(bankIndex, 0); #if 0 /* if line number changed */ if (line_data->line_offset != p_amol->info[field].line[0] && line_data->line_offset != p_amol->info[field].line[1]) { /* which line? */ if (line_data->line_offset < p_amol->info[field].line[1]) p_amol->info[field].line[0] = line_data->line_offset; else p_amol->info[field].line[1] = line_data->line_offset; /* update line mask accordingly */ bapp_amol_mask_lines(p_amol, field); } #endif /* if type changed */ if (20 == line_data->line_offset) i = 0; else i = 1; /* update symbol rate accordingly */ ulRegVal = BREG_Read32(GetREG(), BCHP_AMOLE_0_BYTES_PER_LINE); switch (bankIndex) { case 0: if (i) { ulRegAddr = BCHP_AMOLE_0_DATA_WORD0_BANK0 + 12; ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE22_BANK0); if (AMOL_TYPE_I != line_data->amol_type) ulRegVal |= BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE22_BANK0, 1); /* NOTE if configure lines based on line number, then there is not need for this */ BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK0, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK0 + 4, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK0 + 8, 0); } else { ulRegAddr = BCHP_AMOLE_0_DATA_WORD0_BANK0; ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE20_BANK0); if (AMOL_TYPE_I != line_data->amol_type) ulRegVal |= BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE20_BANK0, 1); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK0 + 12, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK0 + 16, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK0 + 20, 0); } break; case 1: if (i) { ulRegAddr = BCHP_AMOLE_0_DATA_WORD0_BANK1 + 12; ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE22_BANK1); if (AMOL_TYPE_I != line_data->amol_type) ulRegVal |= BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE22_BANK1, 1); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK1, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK1 + 4, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK1 + 8, 0); } else { ulRegAddr = BCHP_AMOLE_0_DATA_WORD0_BANK1; ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE20_BANK1); if (AMOL_TYPE_I != line_data->amol_type) ulRegVal |= BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE20_BANK1, 1); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK1 + 12, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK1 + 16, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK1 + 20, 0); } break; case 2: if (i) { ulRegAddr = BCHP_AMOLE_0_DATA_WORD0_BANK2 + 12; ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE22_BANK2); if (AMOL_TYPE_I != line_data->amol_type) ulRegVal |= BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE22_BANK2, 1); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK2, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK2 + 4, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK2 + 8, 0); } else { ulRegAddr = BCHP_AMOLE_0_DATA_WORD0_BANK2; ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE20_BANK2); if (AMOL_TYPE_I != line_data->amol_type) ulRegVal |= BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE20_BANK2, 1); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK2 + 12, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK2 + 16, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK2 + 20, 0); } break; case 3: if (i) { ulRegAddr = BCHP_AMOLE_0_DATA_WORD0_BANK3 + 12; ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE22_BANK3); if (AMOL_TYPE_I != line_data->amol_type) ulRegVal |= BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE22_BANK3, 1); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK3, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK3 + 4, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK3 + 8, 0); } else { ulRegAddr = BCHP_AMOLE_0_DATA_WORD0_BANK3; ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE20_BANK3); if (AMOL_TYPE_I != line_data->amol_type) ulRegVal |= BCHP_FIELD_DATA ( AMOLE_0_BYTES_PER_LINE, LINE20_BANK3, 1); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK3 + 12, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK3 + 16, 0); BREG_Write32(GetREG(), BCHP_AMOLE_0_DATA_WORD0_BANK3 + 20, 0); } break; } BREG_Write32(GetREG(), BCHP_AMOLE_0_BYTES_PER_LINE, ulRegVal); /* Now write the user's data */ ulRegVal = 0; ulRegVal |= (uint32_t)(*pAMOLData++); ulRegVal |= (uint32_t)(*pAMOLData++) << 8; ulRegVal |= (uint32_t)(*pAMOLData++) << 16; ulRegVal |= (uint32_t)(*pAMOLData++) << 24; BREG_Write32(GetREG(), ulRegAddr, ulRegVal); ulRegAddr += 4; ulRegVal = 0; ulRegVal |= (uint32_t)(*pAMOLData++); ulRegVal |= (uint32_t)(*pAMOLData++) << 8; if (totalBytes > 6) { ulRegVal |= (uint32_t)(*pAMOLData++) << 16; ulRegVal |= (uint32_t)(*pAMOLData++) << 24; BREG_Write32(GetREG(), ulRegAddr, ulRegVal); ulRegAddr += 4; ulRegVal = 0; ulRegVal |= (uint32_t)(*pAMOLData++); ulRegVal |= (uint32_t)(*pAMOLData++) << 8; ulRegVal |= (uint32_t)(*pAMOLData++) << 16; ulRegVal |= (uint32_t)(*pAMOLData++) << 24; } BREG_Write32(GetREG(), ulRegAddr, ulRegVal); /* Program the write pointer into hardware */ ++ulWritePointer; ulRegVal = BCHP_FIELD_DATA (AMOLE_0_WRPTR, VALUE, ulWritePointer); BREG_Write32(GetREG(), BCHP_AMOLE_0_WRPTR, ulRegVal); BDBG_MSG(("%s: leave", __func__)); return 0x0; } uint32_t bapp_amol_set_scte_127_ex( bapp_amol_t p_amol, scte_127_data *line_data1, scte_127_data *line_data2) { uint32_t ulRegVal, status; uint32_t ulRegAddr = 0; uint32_t ulReadPointer; uint32_t ulWritePointer; uint32_t bankIndex; int totalBytes; uint8_t field = 0; uint8_t *pAMOLData; BDBG_MSG(("%s: enter", __func__)); /* validation */ if (!p_amol || !line_data1 || !line_data2) { BDBG_WRN(("%s: null data pointer", __func__)); return -1; } /* the pair must be for same field and different lines */ if (line_data1->field_parity != line_data2->field_parity || line_data1->line_offset == line_data2->line_offset) { BDBG_WRN(("invalid data, drop (%d,%d)(%d,%d)", line_data1->field_parity, line_data1->line_offset, line_data2->field_parity, line_data2->line_offset)); return -1; } /* currently just assume lines are for 20 and 22 only */ if ((20 != line_data1->line_offset && 22 != line_data1->line_offset) || (20 != line_data2->line_offset && 22 != line_data2->line_offset)) { BDBG_WRN(("invalid lines, drop (l1=%d,l2=%d)", line_data1->line_offset, line_data2->line_offset)); return -1; } status = BREG_Read32(GetREG(), BCHP_AMOLE_0_STATUS) & ~BCHP_AMOLE_0_STATUS_reserved0_MASK; BREG_Write32(GetREG(), BCHP_AMOLE_0_STATUS, status); /* Get FIFO pointers */ ulRegVal = BREG_Read32(GetREG(), BCHP_AMOLE_0_WRPTR); ulWritePointer = BCHP_GET_FIELD_DATA (ulRegVal, AMOLE_0_WRPTR, VALUE); bankIndex = ulWritePointer & 0x3; ulRegVal = BREG_Read32(GetREG(), BCHP_AMOLE_0_RDPTR); ulReadPointer = BCHP_GET_FIELD_DATA (ulRegVal, AMOLE_0_RDPTR, VALUE); /* Check for FIFO full */ if (((ulReadPointer & 0x3) == bankIndex) && (ulReadPointer != ulWritePointer)) { if (status & (BCHP_AMOLE_0_STATUS_FIFO_OVERFLOW_MASK | BCHP_AMOLE_0_STATUS_FIFO_UNDERFLOW_MASK)) { BDBG_WRN(("2: OF/UF (idx=%d,W=%d,R=%d,status=0x%08x)", bankIndex, ulReadPointer, ulWritePointer, status)); return -1; } } field = line_data1->field_parity? 0 : 1; /* Handle field misalignment */ if (((bankIndex == 0) || (bankIndex == 2)) && /* top field */ (AMOL_FIELD_TOP != field)) { BDBG_MSG(("top field misalignment, bankIndex=%d", bankIndex)); bapp_amol_program_null(bankIndex, 1); ++ulWritePointer; ulWritePointer %= 8; bankIndex++; bankIndex %= 4; } else if (((bankIndex == 1) || (bankIndex == 3)) && /* bottom filed */ (AMOL_FIELD_BOT != field)) { BDBG_MSG(("bot field misalignment, bankIndex=%d", bankIndex)); bapp_amol_program_null(bankIndex, 1); ++ulWritePointer; ulWritePointer %= 8; bankIndex++; bankIndex %= 4; } bapp_amol_program_null(bankIndex, 0); /* the caller should verify that line offset is valid (10 - 22) */ /* if line number changed */ if (line_data1->line_offset != p_amol->info[field].line[0] && line_data2->line_offset != p_amol->info[field].line[1]) { /* update line mask accordingly */ p_amol->info[field].line[0] = line_data1->line_offset; p_amol->info[field].line[1] = line_data2->line_offset; bapp_amol_mask_lines(p_amol, field); } /* update symbol rate accordingly */ ulRegVal = BREG_Read32(GetREG(), BCHP_AMOLE_0_BYTES_PER_LINE); switch (bankIndex) { case 0: ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE20_BANK0); ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE22_BANK0); if (line_data1->amol_type >= AMOL_TYPE_II_1M) ulRegVal |= BCHP_FIELD_DATA(AMOLE_0_BYTES_PER_LINE, LINE20_BANK0, 1); if (line_data2->amol_type >= AMOL_TYPE_II_1M) ulRegVal |= BCHP_FIELD_DATA(AMOLE_0_BYTES_PER_LINE, LINE22_BANK0, 1); ulRegAddr = BCHP_AMOLE_0_DATA_WORD0_BANK0; break; case 1: ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE20_BANK1); ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE22_BANK1); if (line_data1->amol_type >= AMOL_TYPE_II_1M) ulRegVal |= BCHP_FIELD_DATA(AMOLE_0_BYTES_PER_LINE, LINE20_BANK1, 1); if (line_data2->amol_type >= AMOL_TYPE_II_1M) ulRegVal |= BCHP_FIELD_DATA(AMOLE_0_BYTES_PER_LINE, LINE22_BANK1, 1); ulRegAddr = BCHP_AMOLE_0_DATA_WORD0_BANK1; break; case 2: ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE20_BANK2); ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE22_BANK2); if (line_data1->amol_type >= AMOL_TYPE_II_1M) ulRegVal |= BCHP_FIELD_DATA(AMOLE_0_BYTES_PER_LINE, LINE20_BANK2, 1); if (line_data2->amol_type >= AMOL_TYPE_II_1M) ulRegVal |= BCHP_FIELD_DATA(AMOLE_0_BYTES_PER_LINE, LINE22_BANK2, 1); ulRegAddr = BCHP_AMOLE_0_DATA_WORD0_BANK2; break; case 3: ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE20_BANK3); ulRegVal &= ~BCHP_MASK(AMOLE_0_BYTES_PER_LINE, LINE22_BANK3); if (line_data1->amol_type >= AMOL_TYPE_II_1M) ulRegVal |= BCHP_FIELD_DATA(AMOLE_0_BYTES_PER_LINE, LINE20_BANK3, 1); if (line_data2->amol_type >= AMOL_TYPE_II_1M) ulRegVal |= BCHP_FIELD_DATA(AMOLE_0_BYTES_PER_LINE, LINE22_BANK3, 1); ulRegAddr = BCHP_AMOLE_0_DATA_WORD0_BANK3; break; } BREG_Write32(GetREG(), BCHP_AMOLE_0_BYTES_PER_LINE, ulRegVal); /* Now write the user's data of first line */ if (AMOL_TYPE_I == line_data1->amol_type) { totalBytes = 6; pAMOLData = line_data1->u.amol48; } else { totalBytes = 12; pAMOLData = line_data1->u.amol96; } ulRegVal = 0; ulRegVal |= (uint32_t)(*pAMOLData++); ulRegVal |= (uint32_t)(*pAMOLData++) << 8; ulRegVal |= (uint32_t)(*pAMOLData++) << 16; ulRegVal |= (uint32_t)(*pAMOLData++) << 24; BREG_Write32(GetREG(), ulRegAddr, ulRegVal); ulRegAddr += 4; ulRegVal = 0; ulRegVal |= (uint32_t)(*pAMOLData++); ulRegVal |= (uint32_t)(*pAMOLData++) << 8; if (totalBytes > 6) { ulRegVal |= (uint32_t)(*pAMOLData++) << 16; ulRegVal |= (uint32_t)(*pAMOLData++) << 24; BREG_Write32(GetREG(), ulRegAddr, ulRegVal); ulRegAddr += 4; ulRegVal = 0; ulRegVal |= (uint32_t)(*pAMOLData++); ulRegVal |= (uint32_t)(*pAMOLData++) << 8; ulRegVal |= (uint32_t)(*pAMOLData++) << 16; ulRegVal |= (uint32_t)(*pAMOLData++) << 24; } BREG_Write32(GetREG(), ulRegAddr, ulRegVal); /* write line 22 data */ if (totalBytes > 6) ulRegAddr += 4; else ulRegAddr += 8; /* write line 2 */ if (AMOL_TYPE_I == line_data2->amol_type) { totalBytes = 6; pAMOLData = line_data2->u.amol48; } else { totalBytes = 12; pAMOLData = line_data2->u.amol96; } ulRegVal = 0; ulRegVal |= (uint32_t)(*pAMOLData++); ulRegVal |= (uint32_t)(*pAMOLData++) << 8; ulRegVal |= (uint32_t)(*pAMOLData++) << 16; ulRegVal |= (uint32_t)(*pAMOLData++) << 24; BREG_Write32(GetREG(), ulRegAddr, ulRegVal); ulRegAddr += 4; ulRegVal = 0; ulRegVal |= (uint32_t)(*pAMOLData++); ulRegVal |= (uint32_t)(*pAMOLData++) << 8; if (totalBytes > 6) { ulRegVal |= (uint32_t)(*pAMOLData++) << 16; ulRegVal |= (uint32_t)(*pAMOLData++) << 24; BREG_Write32(GetREG(), ulRegAddr, ulRegVal); ulRegAddr += 4; ulRegVal = 0; ulRegVal |= (uint32_t)(*pAMOLData++); ulRegVal |= (uint32_t)(*pAMOLData++) << 8; ulRegVal |= (uint32_t)(*pAMOLData++) << 16; ulRegVal |= (uint32_t)(*pAMOLData++) << 24; } BREG_Write32(GetREG(), ulRegAddr, ulRegVal); /* Program the write pointer into hardware */ ++ulWritePointer; ulWritePointer %= 8; ulRegVal = BCHP_FIELD_DATA (AMOLE_0_WRPTR, VALUE, ulWritePointer); BREG_Write32(GetREG(), BCHP_AMOLE_0_WRPTR, ulRegVal); BDBG_MSG(("%s: leave", __func__)); return 0x0; }