/*************************************************************************** * Copyright (c) 2012, 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 "led.h" #include "ministd.h" #include "bsettop_types.h" #include "bsettop.h" #include "bsettop_tuner.h" #include "bsettop_decode_audio.h" #include "bsettop_decode.h" #include "bsettop_display.h" #include "bsettop_hdmi.h" #include "bsettop_rfm.h" #include "bgfx.h" #include "bspi_flash.h" unsigned led_set_mode(enum led_mode_t mode) { return 0; } unsigned led_update(unsigned elapsed_time) { return 0; } #define DBG_PRINT(x) printf x #define OSD_WIDTH 720 #if DISPLAY_NTSC #define OSD_HEIGHT 480 #else #if DISPLAY_PAL #define OSD_HEIGHT 576 #else #error display format (NTSC or PAL) must be defined #endif #endif #define OSD_PITCH (720/2) #define NUM_EVENTS 2 #define GRC_TOP_SLOT 0 #define GRC_BOT_SLOT 1 #define FIELD_MASK ((1UL << GRC_TOP_SLOT) | (1UL << GRC_BOT_SLOT)) #define MUTEX_TIMEOUT 100 /* milliseconds */ #define PEND_TIMEOUT 100 /* milliseconds */ typedef enum bgraphics_state_t { eGS_UNINITIALIZED, eGS_DEFAULT, eGS_PALETTE_SET, eGS_PALETTE_LOADED, eGS_FB_SET, }bgraphics_state_t; struct bgraphics { bgraphics_state_t state; unsigned int surf_idx; unsigned int field_mask; unsigned int *p_palette; int format; /* P4 and RGB format */ int pitch; /* pitch associated with format to use */ int bpp; b_queue_t queue; b_mutex_t mutex; b_event_t events[NUM_EVENTS]; bgfx_surf_t surf[2]; }; static struct bgraphics s_graphics = { eGS_UNINITIALIZED, 0, 0, NULL , bgraphics_pixel_format_a8_r8_g8_b8, OSD_PITCH * 8,32 }; extern void get_osd_info(unsigned char **pixels, int *pitch, int *width, int *height); extern void update_osd(); bgraphics_t bgraphics_open( bobject_t id, bdisplay_t display) { unsigned int flags; unsigned char *p_surf; unsigned char *pixels; uint16_t s_width, s_height, s_pitch; int pitch,width,height,bpp; get_osd_info(&pixels,&pitch,&width,&height); s_pitch = (uint16_t)pitch; s_width = (uint16_t)width; s_height = (uint16_t)height; if (s_graphics.state > eGS_UNINITIALIZED) return (bgraphics_t)0; switch (s_graphics.format) { case bgraphics_pixel_format_a8_r8_g8_b8: case bgraphics_pixel_format_y08_cb8_y18_cr8: pitch = width * 4; bpp = 32; break; #if 0 case bgraphics_pixel_format_r5_g6_b5: case bgraphics_pixel_format_a1_r5_g5_b5: case bgraphics_pixel_format_r5_g5_b5_a1: case bgraphics_pixel_format_a4_r4_g4_b4: case bgraphics_pixel_format_r4_g4_b4_a4: pitch = width * 2; bpp = 16; break; case bgraphics_pixel_format_palette4: pitch = width / 2; bpp = 4 break; #endif default: DBG_PRINT(("%s: unsupported foramt %d", __func__, s_graphics.format)); return (bgraphics_t)0; } if (bgfx_create(&s_graphics.surf[0],width,height,NULL, pitch,NULL,BGFX_SURF_BPP(bpp)|BGFX_SURF_RGB) != 0) { BDBG_ASSERT(0); } if (bgfx_create(&s_graphics.surf[1],width,height,NULL, pitch,NULL,BGFX_SURF_BPP(bpp)|BGFX_SURF_RGB) != 0) { BDBG_ASSERT(0); } s_graphics.state = eGS_DEFAULT; s_graphics.pitch = s_graphics.surf[0].surface.pitch; return (bgraphics_t)&s_graphics; } void bgraphics_close( bgraphics_t graphics /* handle returned by bgraphics_open */ ) { bgfx_destroy(&(s_graphics.surf[0])); } void bgraphics_get( bgraphics_settings *settings /* [out] */ ) { } bresult bgraphics_set( const bgraphics_settings *settings ) { return b_ok; } /* Convert ARGB to ABGR */ static inline unsigned int argb_to_abgr(uint32_t pixel) { if ((pixel && 0xFF000000) == 0x00000000) { return 0xFF000000; } return ((0xFF00FF00 & pixel) | ((0x00FF0000 & pixel) >> 16) | ((0x000000FF & pixel) << 16)); } /* ARGB to ABGR with source alpha blend */ static inline unsigned int argb_to_abgr_w_qalpha(uint32_t src_pixel,uint32_t dst_pixel) { if ((src_pixel && 0xFF000000) == 0x00000000) { return dst_pixel; } return ((0xFF00FF00 & src_pixel) | ((0x00FF0000 & src_pixel) >> 16) | ((0x000000FF & src_pixel) << 16)); } static inline uint32_t bgfx_blend_argb_pixels(uint32_t s_pixel,uint32_t d_pixel) { uint32_t sr,sg,sb,sa,dr,dg,db,da,oa; sa = (s_pixel >> 24) & 0xFF; da = (d_pixel >> 24) & 0xFF; if ((sa == 0xFF) || (da == 0x00)) { return s_pixel; } if ((da == 0xFF) && (sa == 0x00)) { return d_pixel; } sr = (s_pixel >> 16) & 0xFF; sg = (s_pixel >> 8) & 0xFF; sb = (s_pixel >> 0) & 0xFF; dr = (d_pixel >> 16) & 0xFF; dg = (d_pixel >> 8) & 0xFF; db = (d_pixel >> 0) & 0xFF; dr = (((sr * sa)/0xFF) & 0xFF) + ((((0xFF - sa) * dr)/0xFF) & 0xFF); dg = (((sg * sa)/0xFF) & 0xFF) + ((((0xFF - sa) * dg)/0xFF) & 0xFF); db = (((sb * sa)/0xFF) & 0xFF) + ((((0xFF - sa) * db)/0xFF) & 0xFF); oa = da; return (oa << 24) | (dr << 16) | (dg << 8) | db; } bresult bgraphics_sync( bgraphics_t g, /* handle returned by bgraphics_open */ bool overlay /* overlay is popped or not */ ) { uint8_t *pixels,*src_pixels; uint32_t *dst,*src; int x,y,pitch,width,height; get_osd_info(&pixels,&pitch,&width,&height); printf("%s:%d\n",__FUNCTION__,__LINE__); src_pixels = g->surf[0].surface.buf; for (y = 0; y < height; ++y) { dst = (uint32_t*)pixels; src = (uint32_t*)src_pixels; for (x = 0; x < width; ++x) { dst[x] = 0xFF000000; dst[x] = bgfx_blend_argb_pixels(src[x],dst[x]); if (!overlay) dst[x] = argb_to_abgr(dst[x]); //dst[x] = argb_to_abgr(src[x]); } pixels += pitch; src_pixels += g->surf[0].surface.pitch; } if (overlay) { get_osd_info(&pixels,&pitch,&width,&height); src_pixels = g->surf[1].surface.buf; for (y = 0; y < height; ++y) { dst = (uint32_t*)pixels; src = (uint32_t*)src_pixels; for (x = 0; x < width; ++x) { //dst[x] = argb_to_abgr_w_qalpha(src[x],dst[x]); dst[x] = argb_to_abgr(bgfx_blend_argb_pixels(src[x],dst[x])); } pixels += pitch; src_pixels += g->surf[0].surface.pitch; } } update_osd(); return b_ok; } bresult bgraphics_sync_partial( bgraphics_t g, /* handle returned by bgraphics_open */ bgraphics_id id, bool overlay /* overlay is popped or not */ ) { return b_ok; } bresult bgraphics_get_framebuffer( bgraphics_t graphics, /* handle returned by bgraphics_open */ void **buffer, /* [out] address of framebuffer memory */ unsigned int **palette, /* [out] address of palette */ int *width, /* [out] width of the OSD surface */ int *height, /* [out] height of the OSD surface */ int *pitch /* [out] pitch of the OSD surface */ ) { *buffer = s_graphics.surf[0].surface.buf; *palette = s_graphics.p_palette; *width = s_graphics.surf[0].surface.width; *height = s_graphics.surf[0].surface.height; *pitch = s_graphics.surf[0].surface.pitch; return b_ok; } bresult bgraphics_get_osd_params(bgraphics_t graphics, bsettop_surf_t *p_osd_surf, void **osd_buffer, bsettop_surf_t *p_overlay_surf, void **overlay_mem) { *p_osd_surf = NULL; *osd_buffer = s_graphics.surf[0].surface.buf; if (overlay_mem) { *p_overlay_surf = NULL; *overlay_mem = s_graphics.surf[1].surface.buf; } return b_ok; } bresult bsurface_create_surface(uint32_t width, uint32_t height, bgraphics_pixel_format format, uint8_t **mem, uint32_t *pitch, bsettop_surf_t *p_settop_surf) { *mem = (uint8_t*)1; return b_ok; } bresult bgraphics_load_palette( bgraphics_t g /* handle returned by bgraphics_open */ ) { return b_ok; } baudio_decode_t baudio_decode_open(bobject_t id) { return (baudio_decode_t)1; } void baudio_decode_close(baudio_decode_t codec) { } bresult baudio_decode_start(baudio_decode_t codec, bdisplay_t display, bstream_t stream) { return b_ok; } void baudio_decode_stop(baudio_decode_t codec) { } bresult baudio_decode_get_status(baudio_decode_t codec, baudio_decode_status *status) { return b_ok; } void baudio_decode_get_config(baudio_decode_t codec, baudio_decode_config *config) { } bresult baudio_decode_set_config(baudio_decode_t codec, const baudio_decode_config *config) { return b_ok; } void baudio_decode_get_avl_level(baudio_decode_t audio, int num_energy, long *level) { *level = 0; } void baudio_decode_test_tone(baudio_decode_t audio, uint32_t *samples, /* array of samples, num_samples long */ uint32_t num_samples, /* Number of samples, should be less than sample array size */ bool leftChannel, /* true - program left channel, flase program right channel */ bool enable /* enable/disable hifidac tone test */ ) { } bdecode_t bdecode_open( bobject_t decode_id /* decode object id */ ) { return (bdecode_t)1; } void bdecode_close( bdecode_t decode /* handle returned by bdecode_open */ ) { } bresult bdecode_start( bdecode_t decode, /* handle returned by bdecode_open */ bstream_t source, /* source for the decode, either analog or digital */ bdecode_window_t window /* window to render decode */ ) { return b_ok; } void bdecode_stop( bdecode_t decode /* handle returned by bdecode_open */ ) { } bresult bdecode_get_status( bdecode_t decode, /* handle returned by bdecode_open */ bdecode_status *status /* [out] status to be populated */ ) { return b_ok; } void bdecode_set_config( bdecode_t decode, /* handle returned by bdecode_open */ bdecode_config *p_cfg /* configuration structure reference */ ) { } void bdecode_get_config( bdecode_t decode, /* handle returned by bdecode_open */ bdecode_config *p_cfg /* [out] configuration to be populated */ ) { } bdisplay_t bdisplay_open( bobject_t display_id /* handle used to identify a particular display */ ) { return (bdisplay_t)1; } void bdisplay_close( bdisplay_t display /* handle returned by bdisplay_open */ ) { } boutput_rf_t boutput_rf_open( bobject_t rfmod_id ) { return (boutput_rf_t)1; } boutput_spdif_t boutput_spdif_open(bobject_t spdif_id) { return (boutput_spdif_t)1; } boutput_i2s_t boutput_i2s_open(bobject_t i2s_id) { return (boutput_i2s_t)1; } bresult bdisplay_set( bdisplay_t display, /* handle returned by bdisplay_open */ bdisplay_settings *settings /* desired display settings */ ) { return b_ok; } void bdisplay_get( bdisplay_t display, /* handle returned by bdisplay_open */ bdisplay_settings *settings /* [out] current settings of display */ ) { } bresult boutput_rf_set(boutput_rf_t rf, const boutput_rf_settings *settings ) { return b_ok; } void boutput_rf_get(boutput_rf_t rf, boutput_rf_settings *settings /* [out] */ ) { } bresult boutput_spdif_set(boutput_spdif_t spdif, const boutput_spdif_settings *settings ) { return b_ok; } void boutput_spdif_get(boutput_spdif_t spdif, boutput_spdif_settings *settings /* [out] */ ) { } bresult boutput_i2s_set(boutput_i2s_t i2s, const boutput_i2s_settings *settings ) { return b_ok; } void boutput_i2s_get(boutput_i2s_t i2s, boutput_i2s_settings *settings /* [out] */ ) { } bresult boutput_rf_set_audio_volume( boutput_rf_t rf, unsigned int volume /* desired volume */ ) { return b_ok; } bresult boutput_rf_get_audio_volume( boutput_rf_t rf, unsigned int *volume /* [out] current volume of the rf modulater */ ) { return b_ok; } bdecode_window_t bdecode_window_open( bobject_t window_id, /* window's object id */ bdisplay_t display /* display on which the window appears */ ) { return (bdecode_window_t)1; } void bdecode_window_close( bdecode_window_t window ) { } bresult bdecode_window_get( bdecode_window_t window, bdecode_window_settings *settings /* [out] */ ) { return b_ok; } bresult bdecode_window_set( bdecode_window_t window, bdecode_window_settings *settings ) { return b_ok; } bresult bdecode_window_preset( bdecode_window_t window, bdecode_window_settings *settings ) { return b_ok; } int b_lock_vdc(void) { } void b_unlock_vdc(void) { } bresult bdisplay_set_vbi_rating_info( bdisplay_t display, unsigned int ratings_tv, unsigned int ratings_movie, unsigned int content_v, unsigned int content_s, unsigned int content_l, unsigned int content_d ) { return b_ok; } bresult bdisplay_output_rf_enable( bdisplay_t display, /* handle returned by bdisplay_open */ bool enable ) { return b_ok; } /** Summary: enable deinterlacer on display (id), and disable deinterlacer on other display (!id) **/ void bdisplay_set_deinterlacer(bdisplay_t display, int id, bool enable) { } void bdisplay_set_coefficient_index(bdisplay_t display,bool horiz, int output, int coeff_idx) { } bresult bdisplay_output_hdmi_enable(bdisplay_t display, bool enable) { return b_ok; } bresult bdisplay_set_init_format(bobject_t display_id, bsettop_display_format_t fmt) { return b_ok; } void bdisplay_get_default_settings(bdisplay_settings *psettings) { } bresult bsettop_init(bsettop_version version) { } bresult smessage_init(void *decode_cfgs) { return b_ok; } bresult bsettop_hdmi_open( bsettop_hdmi_t *h_hdmi, bdisplay_t display, /* display on which the graphics are displayed */ baudio_decode_t audio_decode, bsettop_hdcp_authentication_cb_t hdcp_authentication_cb ) { return b_ok; } void bsettop_hdmi_close(bsettop_hdmi_t h_hdmi) { } bresult boutput_hdmi_get_status(bsettop_hdmi_t h_hdmi, boutput_hdmi_status *status /* [out] */ ) { return b_ok; } brfm_t brfm_open( bobject_t rfm_id /* - index used to identify a particular rfm */ ) { return (brfm_t)1; } /* Summary: Close the rfm. */ void brfm_close( brfm_t rfm /* - handle returned by brfm_open */ ) { } int chm_process_mss(void *p_chm, /* Channel manager reference */ const uint8_t* p_mms, /* Pointer to MMS */ unsigned char* mms_buf, /* string buffer */ unsigned int mms_len /* string buffer length */ ) { return 0; } void chm_init(void *p_chm, void *p_app) { } /* Summary: Function to pass a command to the channel manager. Any results and notification is handled by passing events to the app via the msg_queue. */ void chm_cmd(void *p_chm,void *p_cmd_evt) { } #if 0 void factory_draw(void *v_app, void *v_screen) { } int factory_handle_event(void *v_app, void *v_screen, void *p_event) { return 0; } #endif void image_get_status(void* st) { } /* Jan 1, 1970 => Thursday */ #define START_DAY 3 #define START_YEAR 1970 /* Days/month for non-leap year */ const unsigned char s_days_per_mon[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, }; #define IS_LEAP_YEAR(y) ( !((y + START_YEAR) % 4) && ( ((y + START_YEAR) % 100) || !((y + START_YEAR) % 400) ) ) void utctime(unsigned int secs,b_tm *p_tm) { unsigned int yday,mon,t_val; unsigned char *p_dpm = (unsigned char*)s_days_per_mon; memset(p_tm,0,sizeof(b_tm)); /* seconds */ p_tm->tm_sec = secs % 60; t_val = secs / 60; /* minutes */ /* minutes */ p_tm->tm_min = t_val % 60; t_val /= 60; /* hours */ /* hours */ p_tm->tm_hour = t_val % 24; t_val /= 24; /* day of week */ p_tm->tm_wday = t_val % 7; p_tm->tm_wday = (t_val - START_DAY) % 7; /* offset value to start of the year */ #ifndef LINUX t_val += 5; #endif /* year */ p_tm->tm_yday = t_val; p_tm->tm_year = 0; /* day of current year */ while ((IS_LEAP_YEAR(p_tm->tm_year) && (p_tm->tm_yday > 365)) || (!IS_LEAP_YEAR(p_tm->tm_year) && (p_tm->tm_yday > 364))) { if (IS_LEAP_YEAR(p_tm->tm_year)) p_tm->tm_yday -= 366; else p_tm->tm_yday -= 365; p_tm->tm_year++; } if (IS_LEAP_YEAR(p_tm->tm_year)) p_dpm += 12; yday = p_tm->tm_yday + 1; mon = 0; while(yday > p_dpm[mon]) { yday -= p_dpm[mon]; mon++; } /* month */ p_tm->tm_mon = mon; /* day of month */ p_tm->tm_mday = yday; } bool is_video_format_supported() { return true; } bool bsettop_hdmi_is_video_fmt_supported(bsettop_display_format_t fmt) { return true; } void *image_get_header(int bank, bool *bact) { return NULL; } bool bsettop_hdmi_get_RGB_output(void) { return true; } bresult bsettop_hdmi_set_RGB_output(bool bRGB) { return b_ok; } bool bsettop_hdmi_get_native_audio_mode(void) { return true; } BERR_Code bsettop_hdmi_set_native_audio_mode(bool native) { return BERR_SUCCESS; } bool g_disable_fcc; uint32_t ui32OutputChannelMatrix[1][1]; void bsettop_uninit(void) { } btuner_t btuner_open( bobject_t tuner_id /* - handle used to identify a particular tuner */ ) { return (btuner_t)1; } /* Summary: Close a tuner. */ void btuner_close( btuner_t tuner /* - handle returned by btuner_open */ ) { } bresult btuner_get_softdecisions( btuner_t tuner, btuner_softdecision_t *pdec, /* - [out] array of soft decisions */ size_t length /* number of soft decisions to get */ ) { return b_ok; } bband_t btuner_tune( btuner_t tuner, unsigned freq, /* - RF center frequency in Hz */ btuner_params *params /* - parameters needed to tune and acquire */ ) { return (bband_t)1; } bresult btuner_get_status( btuner_t tuner, btuner_status *status /* - [out] Current status of the SDS demod */ ) { return b_ok; } bresult btuner_reset_status(btuner_t tuner) { return b_ok; } void btuner_params_init( btuner_params *ds, /* - [out] */ btuner_t tuner /* - required for possible resource-dependent defaults */ ) { } int chm_get_hunt_progress(void *p_chm) { return 50; } int chm_get_cdl_progress(void *p_chm) { return 50; } bool chm_is_chmap_updated(void *p_chm) { return true; } bresult bspi_identify( bspi_settings_t *p_settings /* [out] SPI flash settings structure */ ) { p_settings->se_cmd = 0xD8; p_settings->sector_size = 0x10000; p_settings->page_size = 0x100; return b_ok; } int chm_get_time_info(void *p_chm, unsigned int *utc_secs, /* Current UTC time in seconds */ int *local_offset, /* Local time offset from UTC time in seconds */ bool *dst /* Daylight savings flag */ ) { return -1; } void bsettop_pvt() { }