int __init stmcore_display_postinit(struct stmcore_display *p) { stm_display_output_setup_clock_reference(p->main_output, STM_CLOCK_REF_30MHZ, refClockError); stm_display_output_set_control(p->main_output, STM_CTRL_MAX_PIXEL_CLOCK, 27027000); /* * Setup internal configuration controls */ if(maxDAC123Voltage != 0) stm_display_output_set_control(p->main_output, STM_CTRL_DAC123_MAX_VOLTAGE, maxDAC123Voltage); if(maxDAC456Voltage != 0) stm_display_output_set_control(p->main_output, STM_CTRL_DAC456_MAX_VOLTAGE, maxDAC456Voltage); if(DAC123SaturationPoint != 0) stm_display_output_set_control(p->main_output, STM_CTRL_DAC123_SATURATION_POINT, DAC123SaturationPoint); if(DAC456SaturationPoint != 0) stm_display_output_set_control(p->main_output, STM_CTRL_DAC456_SATURATION_POINT, DAC456SaturationPoint); if(claimed_gpio_hotplug) p->hotplug_poll_pio = GPIO_PIN_HOTPLUG; return 0; }
long stmhdmiio_set_audio_source(unsigned int arg) { unsigned long audio = STM_AV_SOURCE_MAIN_INPUT; unsigned long val; long retval=0; printk("%s - %p\n", __func__, HACK_dev); if(mutex_lock_interruptible(&HACK_dev->lock)) return -ERESTARTSYS; switch(arg) { case STMHDMIIO_AUDIO_SOURCE_2CH_I2S: audio |= STM_AV_SOURCE_2CH_I2S_INPUT; break; case STMHDMIIO_AUDIO_SOURCE_SPDIF: audio |= STM_AV_SOURCE_SPDIF_INPUT; break; case STMHDMIIO_AUDIO_SOURCE_8CH_I2S: audio |= STM_AV_SOURCE_8CH_I2S_INPUT; break; case STMHDMIIO_AUDIO_SOURCE_NONE: break; default: retval = -EINVAL; goto exit; } if(stm_display_output_set_control(HACK_dev->hdmi_output, STM_CTRL_AV_SOURCE_SELECT, audio)<0) { if(signal_pending(current)) retval = -ERESTARTSYS; else retval = -EIO; goto exit; } if(stm_display_output_get_control(HACK_dev->hdmi_output, STM_CTRL_AV_SOURCE_SELECT, &val)<0) { if(signal_pending(current)) retval = -EINTR; else retval = -EIO; goto exit; } if(val != audio) retval = -EINVAL; exit: mutex_unlock(&HACK_dev->lock); return retval; }
int __init stmcore_display_postinit(struct stmcore_display *p) { /* * Setup internal configuration controls */ if(maxDAC123Voltage != 0) stm_display_output_set_control(p->main_output, STM_CTRL_DAC123_MAX_VOLTAGE, maxDAC123Voltage); if(maxDAC456Voltage != 0) stm_display_output_set_control(p->main_output, STM_CTRL_DAC456_MAX_VOLTAGE, maxDAC456Voltage); if(DAC123SaturationPoint != 0) stm_display_output_set_control(p->main_output, STM_CTRL_DAC123_SATURATION_POINT, DAC123SaturationPoint); if(DAC456SaturationPoint != 0) stm_display_output_set_control(p->main_output, STM_CTRL_DAC456_SATURATION_POINT, DAC456SaturationPoint); return 0; }
static int stmfb_probe_get_outputs(struct stmfb_info *i,struct stmcore_display_pipeline_data *pd) { i->pFBMainOutput = stm_display_get_output(pd->device, pd->main_output_id); if(!i->pFBMainOutput) return -ENODEV; i->main_config.outputid = STMFBIO_OUTPUTID_MAIN; stmfb_initialise_output_config(i->pFBMainOutput,&i->main_config); if(pd->dvo_output_id != -1) { i->pFBDVO = stm_display_get_output(pd->device, pd->dvo_output_id); i->main_config.caps |= STMFBIO_OUTPUT_CAPS_DVO_CONFIG; i->main_config.dvo_config = (STMFBIO_OUTPUT_DVO_CLIP_VIDEORANGE | STMFBIO_OUTPUT_DVO_YUV_444_16BIT | STMFBIO_OUTPUT_DVO_DISABLED); stm_display_output_set_control(i->pFBDVO, STM_CTRL_SIGNAL_RANGE, STM_SIGNAL_VIDEO_RANGE); } i->hdmi = pd->hdmi_data; if(i->hdmi) { i->main_config.caps |= STMFBIO_OUTPUT_CAPS_HDMI_CONFIG; i->main_config.hdmi_config = (i->hdmi->disable==0)?STMFBIO_OUTPUT_HDMI_ENABLED:STMFBIO_OUTPUT_HDMI_DISABLED; i->main_config.hdmi_config |= (STMFBIO_OUTPUT_HDMI_RGB | STMFBIO_OUTPUT_HDMI_CLIP_VIDEORANGE); if(mutex_lock_interruptible(&i->hdmi->lock)) return -EINTR; stm_display_output_set_control(i->hdmi->hdmi_output, STM_CTRL_SIGNAL_RANGE, STM_SIGNAL_VIDEO_RANGE); mutex_unlock(&i->hdmi->lock); } return 0; }
static int stmfbio_post_auth(struct stmfb_info *i, unsigned int auth) { struct stm_hdmi *hdmi = i->hdmi; int res = 0; if(!hdmi) return -ENODEV; if(mutex_lock_interruptible(&hdmi->lock)) return -ERESTARTSYS; if (STM_DISPLAY_CONNECTED == hdmi->status) { stm_display_output_set_control(hdmi->hdmi_output, STM_CTRL_HDMI_POSTAUTH, auth); hdmi->auth = auth; } else { hdmi->auth = 0; res = -ENODEV; } mutex_unlock(&hdmi->lock); return res; }
int stmfb_ioctl(struct fb_info* fb, u_int cmd, u_long arg) { struct stmfb_info* i = (struct stmfb_info* )fb; switch (cmd) { case STMFBIO_GET_OUTPUTSTANDARDS: { struct stmfbio_outputstandards standards, *user = (void *) arg; DPRINTK("STMFBIO_GET_OUTPUTSTANDARDS\n"); if (get_user(standards.outputid, &user->outputid)) return -EFAULT; if (standards.outputid != STMFBIO_OUTPUTID_MAIN) return -EINVAL; if (down_interruptible(&i->framebufferLock)) return -ERESTARTSYS; stmfb_get_outputstandards(i, &standards); up(&i->framebufferLock); if (put_user (standards.all_standards, &user->all_standards)) return -EFAULT; return 0; } break; case STMFBIO_GET_OUTPUTINFO: { struct stmfbio_outputinfo info, *user = (void *) arg; int ret; DPRINTK("STMFBIO_GET_OUTPUTINFO\n"); if (get_user(info.outputid, &user->outputid)) return -EFAULT; if (info.outputid != STMFBIO_OUTPUTID_MAIN) return -EINVAL; if(down_interruptible(&i->framebufferLock)) return -ERESTARTSYS; if (!i->current_videomode_valid) { up(&i->framebufferLock); return -EAGAIN; } ret = stmfb_videomode_to_outputinfo(&i->current_videomode, &info); up(&i->framebufferLock); if (!ret && copy_to_user ((void *) arg, &info, sizeof (info))) return -EFAULT; return ret; } break; case STMFBIO_SET_OUTPUTINFO: { struct stmfbio_outputinfo info; struct stmfb_videomode vm; int ret; DPRINTK("STMFBIO_SET_OUTPUTINFO\n"); if (copy_from_user (&info, (void *) arg, sizeof (info))) return -EFAULT; if (info.outputid != STMFBIO_OUTPUTID_MAIN) return -EINVAL; if (down_interruptible (&i->framebufferLock)) return -ERESTARTSYS; /* prevent the framebuffer kernel API from messing around w/ the config in the future, until all apps have exited */ i->fbdev_api_suspended = 1; ret = stmfb_outputinfo_to_videomode (i, &info, &vm); up (&i->framebufferLock); if (!ret) { /* * Re-create the VAR from the exact hardware description, this gives a * completely clean var, which is why we have to save and restore the * activate flags. Without this we get spurious mode changes when they * should have been just tests. */ enum _stmfbio_activate activate = info.activate; ret = stmfb_videomode_to_outputinfo (&vm, &info); info.activate = activate; if (!ret && ((activate & STMFBIO_ACTIVATE_MASK) == STMFBIO_ACTIVATE_IMMEDIATE)) ret = stmfb_set_videomode (info.outputid, &vm, i); if (!ret && copy_to_user ((void *) arg, &info, sizeof (info))) return -EFAULT; } return ret; } break; case STMFBIO_GET_PLANEMODE: { struct stmfbio_planeinfo plane, *user = (void *) arg; DPRINTK("STMFBIO_GET_PLANEMODE\n"); if (get_user (plane.layerid, &user->layerid)) return -EFAULT; if (plane.layerid != 0) return -EINVAL; if (down_interruptible (&i->framebufferLock)) return -ERESTARTSYS; if (!i->current_planeconfig_valid) { up (&i->framebufferLock); return -EAGAIN; } plane.config = i->current_planeconfig; plane.activate = STMFBIO_ACTIVATE_IMMEDIATE; up (&i->framebufferLock); if (copy_to_user ((void *) arg, &plane, sizeof (plane))) return -EFAULT; return 0; } break; case STMFBIO_SET_PLANEMODE: { struct stmfbio_planeinfo plane; int ret; DPRINTK("STMFBIO_SET_PLANEMODE\n"); if (copy_from_user (&plane, (void *) arg, sizeof (plane))) return -EFAULT; if (plane.layerid != 0) return -EINVAL; plane.config.bitdepth = stmfb_bitdepth_for_pixelformat (plane.config.format); if(down_interruptible(&i->framebufferLock)) return -ERESTARTSYS; ret = stmfb_verify_planeinfo (i, &plane); up(&i->framebufferLock); if (!ret && ((plane.activate & STMFBIO_ACTIVATE_MASK) == STMFBIO_ACTIVATE_IMMEDIATE)) ret = stmfb_set_planemode (&plane, i); return ret; } break; case STMFBIO_PAN_PLANE: { struct stmfbio_plane_pan pan; int ret; DPRINTK("STMFBIO_PAN_PLANE\n"); if (copy_from_user (&pan, (void *) arg, sizeof (pan))) return -EFAULT; if (pan.layerid != 0) return -EINVAL; if (down_interruptible (&i->framebufferLock)) return -ERESTARTSYS; /* prevent the framebuffer kernel API from messing around w/ the config in the future, until all apps have exited */ i->fbdev_api_suspended = 1; ret = stmfb_set_plane_pan (&pan, i); up (&i->framebufferLock); return ret; } break; case STMFBIO_GET_VAR_SCREENINFO_EX: { DPRINTK("STMFBIO_GET_VAR_SCREENINFO_EX\n"); if(down_interruptible(&i->framebufferLock)) return -ERESTARTSYS; if(copy_to_user((void*)arg,&i->current_var_ex,sizeof(struct stmfbio_var_screeninfo_ex))) { up(&i->framebufferLock); return -EFAULT; } up(&i->framebufferLock); break; } case STMFBIO_SET_VAR_SCREENINFO_EX: { struct stmfbio_var_screeninfo_ex tmp; int ret; DPRINTK("STMFBIO_SET_VAR_SCREENINFO_EX\n"); if(copy_from_user(&tmp, (void*)arg, sizeof(tmp))) return -EFAULT; if(down_interruptible(&i->framebufferLock)) return -ERESTARTSYS; /* * If we don't have a valid videomode, change an immediate activation to * a deferred one; the settings will take effect when the next valid video * mode is set. */ if(!i->current_planeconfig_valid && tmp.activate == STMFBIO_ACTIVATE_IMMEDIATE) tmp.activate = STMFBIO_ACTIVATE_ON_NEXT_CHANGE; ret = stmfb_set_var_ex(&tmp, i); up(&i->framebufferLock); if(ret != 0) { /* * Copy back the var to set the failed entry */ if(copy_to_user((void*)arg,&tmp, sizeof(tmp))) return -EFAULT; return ret; } break; } case STMFBIO_GET_OUTPUT_CONFIG: { struct stmfbio_output_configuration tmp; int ret; DPRINTK("STMFBIO_GET_OUTPUT_CONFIG\n"); if(copy_from_user(&tmp, (void*)arg, sizeof(tmp))) return -EFAULT; if(down_interruptible(&i->framebufferLock)) return -ERESTARTSYS; ret = stmfb_get_output_configuration(&tmp,i); up(&i->framebufferLock); if(ret == 0) { if(copy_to_user((void*)arg,&tmp,sizeof(tmp))) ret = -EFAULT; } return ret; } case STMFBIO_SET_OUTPUT_CONFIG: { struct stmfbio_output_configuration tmp; int ret; DPRINTK("STMFBIO_SET_OUTPUT_CONFIG\n"); if(copy_from_user(&tmp, (void*)arg, sizeof(tmp))) return -EFAULT; if(down_interruptible(&i->framebufferLock)) return -ERESTARTSYS; ret = stmfb_set_output_configuration(&tmp, i); up(&i->framebufferLock); if(ret != 0) { /* * Copy back the var to set the failed entry */ copy_to_user((void*)arg,&tmp, sizeof(tmp)); return ret; } break; } case STMFBIO_SET_PICTURE_CONFIG: { struct stmfbio_picture_configuration tmp; int ret; DPRINTK("STMFBIO_SET_PICTURE_CONFIG\n"); if(copy_from_user(&tmp, (void*)arg, sizeof(tmp))) return -EFAULT; if(down_interruptible(&i->framebufferLock)) return -ERESTARTSYS; ret = stmfb_set_picture_configuration(&tmp, i); up(&i->framebufferLock); return ret; } case STMFBIO_GET_AUXMEMORY2: { struct stmfbio_auxmem2 auxmem; if (copy_from_user (&auxmem, (void *) arg, sizeof (auxmem))) return -EFAULT; if (auxmem.index >= ARRAY_SIZE (i->AuxBase)) return -EINVAL; auxmem.physical = i->AuxBase[auxmem.index]; auxmem.size = i->AuxSize[auxmem.index]; if (copy_to_user ((void *) arg, &auxmem, sizeof (auxmem))) return -EFAULT; break; } case STMFBIO_GET_SHARED_AREA: { struct stmfbio_shared shared; shared.physical = i->ulPSharedAreaBase; shared.size = i->ulSharedAreaSize; if (copy_to_user ((void *) arg, &shared, sizeof (shared))) return -EFAULT; break; } case STMFBIO_BLT: { int ret; if(down_interruptible(&i->framebufferLock)) return -ERESTARTSYS; ret = stmfbio_blt(i, arg); up(&i->framebufferLock); if(ret<0) { if(signal_pending(current)) return -ERESTARTSYS; else return ret; } break; } case STMFBIO_SET_BLITTER_PALETTE: return stmfbio_set_blitter_palette(i, arg); case STMFBIO_SYNC_BLITTER: { int err; if (!i->pBlitter) return -ENODEV; if(down_interruptible(&i->framebufferLock)) { DPRINTK(" taking framebuffer lock interrupted\n"); return -ERESTARTSYS; } if((err = stm_display_blitter_sync(i->pBlitter)) != 0) { up(&i->framebufferLock); if(signal_pending(current)) { DPRINTK(" sync interrupted\n"); return -ERESTARTSYS; } else { DPRINTK(" sync error! code = %d\n",err); return -EIO; } } up(&i->framebufferLock); break; } case STMFBIO_WAIT_NEXT: { int err; if (!i->pBlitter) return -ENODEV; if(down_interruptible(&i->framebufferLock)) { DPRINTK(" taking framebuffer lock interrupted\n"); return -ERESTARTSYS; } if((err = stm_display_blitter_waitnext(i->pBlitter)) != 0) { up(&i->framebufferLock); if(signal_pending(current)) { DPRINTK(" wait_next interrupted\n"); return -ERESTARTSYS; } else { DPRINTK(" wait_next error! code = %d\n",err); return -EIO; } } up(&i->framebufferLock); break; } case STMFBIO_GET_BLTLOAD: { if (!i->pBlitter) return -ENODEV; return put_user (stm_display_blitter_get_bltload (i->pBlitter), (unsigned long *) arg); } case STMFBIO_PRE_AUTH: return stmfbio_pre_auth(i); case STMFBIO_POST_AUTH: return stmfbio_post_auth(i, arg); case STMFBIO_WAIT_FOR_REAUTH: return stmfbio_wait_for_reauth(i, arg); case STMFBIO_SET_DAC_HD_POWER: { if(down_interruptible(&i->framebufferLock)) return -ERESTARTSYS; stm_display_output_set_control(i->pFBMainOutput, STM_CTRL_DAC_HD_POWER, arg); up(&i->framebufferLock); return 0; } case STMFBIO_SET_DAC_HD_FILTER: { if(down_interruptible(&i->framebufferLock)) return -ERESTARTSYS; stm_display_output_set_control(i->pFBMainOutput, STM_CTRL_DAC_HD_FILTER, arg); up(&i->framebufferLock); return 0; } case STMFBIO_SET_CGMS_ANALOG: { if(down_interruptible(&i->framebufferLock)) return -ERESTARTSYS; stm_display_output_set_control(i->pFBMainOutput, STM_CTRL_CGMS_ANALOG, arg); up(&i->framebufferLock); return 0; } case FBIO_WAITFORVSYNC: { struct stmcore_display_pipeline_data *pd = *((struct stmcore_display_pipeline_data **)i->platformDevice->dev.platform_data); DPRINTK("FBIO_WAITFORVSYNC\n"); if(down_interruptible(&i->framebufferLock)) return -ERESTARTSYS; if(!i->current_videomode_valid) { up(&i->framebufferLock); return -ENODEV; } up(&i->framebufferLock); interruptible_sleep_on(&pd->display_runtime->vsync_wait_queue); if(signal_pending(current)) return -ERESTARTSYS; break; } case FBIOGET_VBLANK: { struct stmcore_display_pipeline_data *pd = *((struct stmcore_display_pipeline_data **)i->platformDevice->dev.platform_data); struct fb_vblank vblank; vblank.flags = FB_VBLANK_HAVE_COUNT; vblank.count = atomic_read (&pd->display_runtime->vsync_count); if (copy_to_user ((void *) arg, &vblank, sizeof (vblank))) return -EFAULT; break; } default: { DPRINTK(" Invalid IOCTL code 0x%08x\n",cmd); return -ENOTTY; } } return 0; }
int main(int argc, char **argv) { stm_display_plane_t *pPlane; stm_display_buffer_t buffer_setup; char *fbuffer; void *fbufferphys; interrupt_t *vsync_interrupt=0; interrupt_t *hdmi_interrupt=0; int err; int seconds; int clip; int rgb; int dvi; stm_plane_id_t planeid; osclock_t lasttime; kernel_initialize(NULL); kernel_start(); kernel_timeslice(OS21_TRUE); framerate_sem = semaphore_create_fifo(0); frameupdate_sem = semaphore_create_fifo(0); hotplug_sem = semaphore_create_fifo(0); task_create(displayupdate_task_fn, 0, OS21_DEF_MIN_STACK_SIZE, MAX_USER_PRIORITY, "displayupdate", 0); pDev = stm_display_get_device(0); if(!pDev) { printf("Unable to create device instance\n"); return 1; } if(argc<2) usage(); argc--; argv++; seconds = 60; rgb = 0; dvi = 0; clip = 0; while(argc>0) { switch(**argv) { case 'C': { printf("Clipping video signal selected\n"); clip = 1; break; } case 'd': { printf("Setting DVI mode on HDMI output\n"); dvi = 1; break; } case 'h': { int refresh; argc--; argv++; if(argc <= 0) { fprintf(stderr,"Missing HD vertical refresh frequency\n"); usage(); } refresh = atoi(*argv); switch(refresh) { case 50: printf("Setting 1280x720-50\n"); MODE = STVTG_TIMING_MODE_720P50000_74250; STANDARD = STM_OUTPUT_STD_SMPTE296M; framerate = 50; break; case 59: printf("Setting 1280x720-59\n"); MODE = STVTG_TIMING_MODE_720P59940_74176; STANDARD = STM_OUTPUT_STD_SMPTE296M; framerate = 60; break; case 60: printf("Setting 1280x720-60\n"); MODE = STVTG_TIMING_MODE_720P60000_74250; STANDARD = STM_OUTPUT_STD_SMPTE296M; framerate = 60; break; default: fprintf(stderr,"Unsupported HD vertical refresh frequency\n"); usage(); } break; } case 'r': { printf("Setting Component RGB Outputs\n"); rgb = 1; break; } case 'p': { int refresh; argc--; argv++; if(argc <= 0) { fprintf(stderr,"Missing 1080p vertical refresh frequency\n"); usage(); } refresh = atoi(*argv); switch(refresh) { case 23: printf("Setting 1920x1080-23\n"); MODE = STVTG_TIMING_MODE_1080P23976_74176; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 24; break; case 24: printf("Setting 1920x1080-24\n"); MODE = STVTG_TIMING_MODE_1080P24000_74250; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 24; break; case 25: printf("Setting 1920x1080-25\n"); MODE = STVTG_TIMING_MODE_1080P25000_74250; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 25; break; case 29: printf("Setting 1920x1080-29\n"); MODE = STVTG_TIMING_MODE_1080P29970_74176; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 30; break; case 30: printf("Setting 1920x1080-30\n"); MODE = STVTG_TIMING_MODE_1080P30000_74250; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 30; break; case 50: printf("Setting 1920x1080-50\n"); MODE = STVTG_TIMING_MODE_1080P50000_148500; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 50; break; case 59: printf("Setting 1920x1080-59\n"); MODE = STVTG_TIMING_MODE_1080P59940_148352; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 60; break; case 60: printf("Setting 1920x1080-60\n"); MODE = STVTG_TIMING_MODE_1080P60000_148500; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 60; break; default: fprintf(stderr,"Unsupported HD vertical refresh frequency\n"); usage(); } break; } case 's': { int refresh; argc--; argv++; if(argc <= 0) { fprintf(stderr,"Missing SD vertical refresh frequency\n"); usage(); } refresh = atoi(*argv); switch(refresh) { case 50: printf("Setting 720x576-50\n"); MODE = STVTG_TIMING_MODE_576P50000_27000; STANDARD = STM_OUTPUT_STD_SMPTE293M; framerate = 50; break; case 59: printf("Setting 720x480-59\n"); MODE = STVTG_TIMING_MODE_480P59940_27000; STANDARD = STM_OUTPUT_STD_SMPTE293M; framerate = 60; break; case 60: printf("Setting 720x480-60\n"); MODE = STVTG_TIMING_MODE_480P60000_27027; STANDARD = STM_OUTPUT_STD_SMPTE293M; framerate = 60; break; default: fprintf(stderr,"Unsupported SD vertical refresh frequency\n"); usage(); } break; } case 't': { argc--; argv++; if(argc <= 0) { fprintf(stderr,"Missing seconds\n"); usage(); } seconds = atoi(*argv); if(seconds<0) usage(); break; } case 'v': { int refresh; argc--; argv++; if(argc <= 0) { fprintf(stderr,"Missing vertical refresh frequency\n"); usage(); } refresh = atoi(*argv); switch(refresh) { case 59: printf("Setting 640x480-59\n"); MODE = STVTG_TIMING_MODE_480P59940_25180; STANDARD = STM_OUTPUT_STD_VESA; framerate = 60; break; case 60: printf("Setting 640x480-60\n"); MODE = STVTG_TIMING_MODE_480P60000_25200; STANDARD = STM_OUTPUT_STD_VESA; framerate = 60; break; default: fprintf(stderr,"Unsupported vertical refresh frequency\n"); usage(); } break; } default: fprintf(stderr,"Unknown option '%s'\n",*argv); usage(); } argc--; argv++; } planeid = OUTPUT_GDP1; vsync_interrupt = get_main_vtg_interrupt(); setup_soc(); if(!vsync_interrupt) { printf("Cannot find VSYNC interrupt handler\n"); return 1; } err = interrupt_install(vsync_interrupt, vsync_isr, pDev); err += interrupt_enable(vsync_interrupt); if(err>0) { printf("Unable to install and enable VSYNC interrupt\n"); return 1; } fbuffer = (char *)malloc(FBSIZE); if(!fbuffer) { printf("Unable to allocate framebuffer\n"); return 1; } memset(fbuffer, 0x00, FBSIZE); create_test_pattern(fbuffer, FBWIDTH, FBHEIGHT, FBSTRIDE); cache_purge_data(fbuffer, FBSIZE); pOutput = stm_display_get_output(pDev, 0); if(!pOutput) { printf("Unable to get output\n"); return 1; } setup_analogue_voltages(pOutput); stm_display_output_set_control(pOutput, STM_CTRL_SIGNAL_RANGE, clip?STM_SIGNAL_VIDEO_RANGE:STM_SIGNAL_FILTER_SAV_EAV); pDVO = get_dvo_output(pDev); { pHDMI = get_hdmi_output(pDev); if(pHDMI) { /* * Now we have a HDMI output pointer to handle hotplug interrupts, * we can enable the interrupt handlers. */ hdmi_interrupt = get_hdmi_interrupt(); if(hdmi_interrupt) { err = interrupt_install(hdmi_interrupt, hdmi_isr, pHDMI); err += interrupt_enable(hdmi_interrupt); } if(err>0) { printf("Unable to install and enable hdmi interrupts\n"); return 1; } stm_display_output_set_control(pHDMI, STM_CTRL_SIGNAL_RANGE, clip?STM_SIGNAL_VIDEO_RANGE:STM_SIGNAL_FILTER_SAV_EAV); } else { printf("Hmmm, no HDMI output available\n"); } } pModeLine = stm_display_output_get_display_mode(pOutput, MODE); if(!pModeLine) { printf("Unable to use requested display mode\n"); return 1; } pPlane = stm_display_get_plane(pDev, planeid); if(!pPlane) { printf("Unable to get graphics plane\n"); return 1; } if(stm_display_plane_connect_to_output(pPlane, pOutput)<0) { printf("Unable to display plane on output\n"); return 1; } if(stm_display_plane_lock(pPlane)<0) { printf("Unable to lock plane's buffer queue\n"); return 1; } memset(&buffer_setup, 0, sizeof(buffer_setup)); vmem_virt_to_phys(fbuffer, &fbufferphys); buffer_setup.src.ulVideoBufferAddr = (ULONG)fbufferphys; buffer_setup.src.ulVideoBufferSize = FBSIZE; buffer_setup.src.ulStride = FBSTRIDE; buffer_setup.src.ulPixelDepth = FBDEPTH; buffer_setup.src.ulColorFmt = FBPIXFMT; buffer_setup.src.Rect.width = FBWIDTH; buffer_setup.src.Rect.height = FBHEIGHT; buffer_setup.dst.Rect.width = FBWIDTH; buffer_setup.dst.Rect.height = FBHEIGHT; buffer_setup.info.ulFlags = STM_PLANE_PRESENTATION_PERSISTENT; printf("Clock is running at %ld ticks per second\n",(long)time_ticks_per_sec()); ULONG format=0; format = rgb?STM_VIDEO_OUT_RGB:STM_VIDEO_OUT_YUV; stm_display_output_set_control(pOutput, STM_CTRL_VIDEO_OUT_SELECT, format); if(pHDMI) { ULONG format = 0; format |= rgb?STM_VIDEO_OUT_RGB:STM_VIDEO_OUT_YUV; format |= dvi?STM_VIDEO_OUT_DVI:STM_VIDEO_OUT_HDMI; stm_display_output_set_control(pHDMI, STM_CTRL_VIDEO_OUT_SELECT, format); } if(stm_display_output_start(pOutput, pModeLine, STANDARD)<0) { printf("Unable to start display\n"); return 1; } if(pDVO) { printf("Info: Attempting to start DVO\n"); if(stm_display_output_start(pDVO, pModeLine, STANDARD)<0) { printf("Info: Unable to start DVO\n"); } } lasttime = time_now(); // VTG Start time (approx) if(stm_display_plane_queue_buffer(pPlane, &buffer_setup)<0) { printf("Unable to queue framebuffer for display on graphics plane\n"); return 1; } task_create(hotplug_task_fn, 0, OS21_DEF_MIN_STACK_SIZE, MIN_USER_PRIORITY, "hotplug", 0); if(seconds == 0) { task_delay(time_ticks_per_sec()*5); task_priority_set(NULL,MIN_USER_PRIORITY); silent_hotplug = 1; err = get_yesno(); } else { while(seconds>0) { osclock_t now,delta; semaphore_wait(framerate_sem); now = time_now(); delta = time_minus(now,lasttime); printf("%d frames took %ld ticks.\n",framerate, (long)delta); lasttime = now; seconds--; } err = 0; } stm_display_plane_flush(pPlane); stm_display_plane_disconnect_from_output(pPlane, pOutput); stm_display_output_stop(pOutput); interrupt_disable(vsync_interrupt); interrupt_disable(hdmi_interrupt); stm_display_plane_release(pPlane); if(pDVO) stm_display_output_release(pDVO); if(pHDMI) stm_display_output_release(pHDMI); stm_display_output_release(pOutput); stm_display_release_device(pDev); return err; }
static int stmhdmi_enable_link(struct stm_hdmi *hdmi) { int n; const stm_mode_line_t *mode; ULONG tvStandard = STM_OUTPUT_STD_CEA861C; if(hdmi->edid_info.display_type == STM_DISPLAY_INVALID) { DPRINTK("Invalid EDID: Not enabling link\n"); return -ENODEV; } /* * Get the master output's mode, this is what we want to set */ mode = stm_display_output_get_current_display_mode(hdmi->main_output); if(!mode) return -EINVAL; if(hdmi->edid_info.display_type == STM_DISPLAY_DVI) { /* * We believe we now have a computer monitor or a TV with a DVI input not * a HDMI input. So set the output format to DVI and force RGB. */ DPRINTK("Setting DVI/RGB output\n"); stm_display_output_set_control(hdmi->hdmi_output, STM_CTRL_VIDEO_OUT_SELECT, (STM_VIDEO_OUT_DVI | STM_VIDEO_OUT_RGB)); if((mode->ModeParams.OutputStandards & STM_OUTPUT_STD_CEA861C) == 0) { /* * To a DVI display we are going to allow pure VESA and NTG5 standards */ if(mode->ModeParams.OutputStandards & STM_OUTPUT_STD_VESA) tvStandard = STM_OUTPUT_STD_VESA; else if(mode->ModeParams.OutputStandards & STM_OUTPUT_STD_NTG5) tvStandard = STM_OUTPUT_STD_NTG5; else return -EINVAL; } } else { if(stmhdmi_determine_pixel_repetition(hdmi,&mode,&tvStandard)!=0) return -EINVAL; stmhdmi_configure_hdmi_formatting(hdmi); } /* * If we have been asked not to check against the EDID, just start * the mode. */ if(hdmi->non_strict_edid_semantics) return stmhdmi_output_start(hdmi, mode, tvStandard); for(n=0;n<hdmi->edid_info.num_modes;n++) { const stm_mode_line_t *tmp = hdmi->edid_info.display_modes[n]; /* * We match up the analogue display mode with the EDID mode by using the * HDMI video codes. */ if(tmp->ModeParams.HDMIVideoCodes[AR_INDEX_4_3] == mode->ModeParams.HDMIVideoCodes[AR_INDEX_4_3] && tmp->ModeParams.HDMIVideoCodes[AR_INDEX_16_9] == mode->ModeParams.HDMIVideoCodes[AR_INDEX_16_9]) { return stmhdmi_output_start(hdmi, mode, tvStandard); } } DPRINTK("Current video mode not reported as supported by display\n"); /* * We are still trying to only set modes indicated as valid in the EDID. So * for DVI devices allow modes that are inside the timing limits. */ if(hdmi->edid_info.display_type == STM_DISPLAY_DVI) return stmhdmi_enable_mode_by_timing_limits(hdmi, mode, tvStandard); return -EINVAL; }
/****************************************************************************** * Functions to check the EDID for a valid mode and enable the HDMI output */ static void stmhdmi_configure_hdmi_formatting(struct stm_hdmi *hdmi) { ULONG video_type; ULONG colour_depth; ULONG quantization = 0; ULONG sink_supports_deepcolour; /* * We are connected to a CEA conformant HDMI device. In this case the spec * says we must do HDMI; if the device does not support YCrCb then force * RGB output. */ if(hdmi->edid_info.cea_capabilities & (STM_CEA_CAPS_YUV|STM_CEA_CAPS_422)) { video_type = hdmi->video_type & (STM_VIDEO_OUT_RGB | STM_VIDEO_OUT_YUV | STM_VIDEO_OUT_422); } else { video_type = STM_VIDEO_OUT_RGB; } DPRINTK("Setting HDMI output format %s\n",(video_type&STM_VIDEO_OUT_RGB)?"RGB":"YUV"); sink_supports_deepcolour = (hdmi->edid_info.hdmi_vsdb_flags & STM_HDMI_VSDB_DC_MASK)?1:0; stm_display_output_set_control(hdmi->hdmi_output, STM_CTRL_HDMI_SINK_SUPPORTS_DEEPCOLOUR, sink_supports_deepcolour); /* * Filter the requested colour depth based on the EDID and colour format, * falling back to standard colour if there is any mismatch. */ if(!sink_supports_deepcolour || (video_type & STM_VIDEO_OUT_422) || ((video_type & STM_VIDEO_OUT_YUV) && !(hdmi->edid_info.hdmi_vsdb_flags & STM_HDMI_VSDB_DC_Y444))) { DPRINTK("Deepcolour not supported in requested colour format\n"); colour_depth = STM_VIDEO_OUT_HDMI_COLOURDEPTH_24BIT; } else { switch(hdmi->video_type & STM_VIDEO_OUT_HDMI_COLOURDEPTH_MASK) { case STM_VIDEO_OUT_HDMI_COLOURDEPTH_30BIT: if(hdmi->edid_info.hdmi_vsdb_flags & STM_HDMI_VSDB_DC_30BIT) colour_depth = STM_VIDEO_OUT_HDMI_COLOURDEPTH_30BIT; else colour_depth = STM_VIDEO_OUT_HDMI_COLOURDEPTH_24BIT; break; case STM_VIDEO_OUT_HDMI_COLOURDEPTH_36BIT: if(hdmi->edid_info.hdmi_vsdb_flags & STM_HDMI_VSDB_DC_36BIT) colour_depth = STM_VIDEO_OUT_HDMI_COLOURDEPTH_36BIT; else colour_depth = STM_VIDEO_OUT_HDMI_COLOURDEPTH_24BIT; break; case STM_VIDEO_OUT_HDMI_COLOURDEPTH_48BIT: if(hdmi->edid_info.hdmi_vsdb_flags & STM_HDMI_VSDB_DC_48BIT) colour_depth = STM_VIDEO_OUT_HDMI_COLOURDEPTH_48BIT; else colour_depth = STM_VIDEO_OUT_HDMI_COLOURDEPTH_24BIT; break; case STM_VIDEO_OUT_HDMI_COLOURDEPTH_24BIT: default: colour_depth = STM_VIDEO_OUT_HDMI_COLOURDEPTH_24BIT; break; } } switch(colour_depth) { case STM_VIDEO_OUT_HDMI_COLOURDEPTH_24BIT: DPRINTK("Setting 24bit colour\n"); break; case STM_VIDEO_OUT_HDMI_COLOURDEPTH_30BIT: DPRINTK("Setting 30bit colour\n"); break; case STM_VIDEO_OUT_HDMI_COLOURDEPTH_36BIT: DPRINTK("Setting 36bit colour\n"); break; case STM_VIDEO_OUT_HDMI_COLOURDEPTH_48BIT: DPRINTK("Setting 48bit colour\n"); break; } stm_display_output_set_control(hdmi->hdmi_output, STM_CTRL_VIDEO_OUT_SELECT, (STM_VIDEO_OUT_HDMI | video_type | colour_depth)); if(hdmi->edid_info.cea_vcdb_flags & STM_CEA_VCDB_QS_RGB_QUANT) quantization |= (ULONG)STM_HDMI_AVI_QUANTIZATION_RGB; if(hdmi->edid_info.cea_vcdb_flags & STM_CEA_VCDB_QY_YCC_QUANT) quantization |= (ULONG)STM_HDMI_AVI_QUANTIZATION_YCC; stm_display_output_set_control(hdmi->hdmi_output, STM_CTRL_HDMI_AVI_QUANTIZATION, quantization); if(hdmi->cea_mode_from_edid) { ULONG tmp = (hdmi->edid_info.tv_aspect == STM_WSS_4_3)?STM_HDMI_CEA_MODE_4_3:STM_HDMI_CEA_MODE_16_9; stm_display_output_set_control(hdmi->hdmi_output, STM_CTRL_HDMI_CEA_MODE_SELECT, tmp); } }
static long stmhdmi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct stm_hdmi *dev = (struct stm_hdmi *)filp->private_data; long retval=0; if(mutex_lock_interruptible(&dev->lock)) return -ERESTARTSYS; switch(cmd) { case STMHDMIIO_SET_SPD_DATA: retval = stmhdmi_set_spd_data(dev, arg); break; case STMHDMIIO_SEND_DATA_PACKET: retval = stmhdmi_send_data_packet(dev, arg); break; case STMHDMIIO_SET_ISRC_DATA: retval = stmhdmi_set_isrc_data(dev, arg); break; case STMHDMIIO_FLUSH_DATA_PACKET_QUEUE: stmhdmi_flush_data_packet_queue(dev,arg); break; case STMHDMIIO_SET_AUDIO_DATA: retval = stmhdmi_set_audio_iframe_data(dev, arg); break; case STMHDMIIO_SET_AVMUTE: if(stm_display_output_set_control(dev->hdmi_output, STM_CTRL_AVMUTE, arg)<0) { if(signal_pending(current)) retval = -ERESTARTSYS; else retval = -EIO; } break; case STMHDMIIO_SET_AUDIO_SOURCE: { unsigned long audio = STM_AV_SOURCE_MAIN_INPUT; unsigned long val; switch(arg) { case STMHDMIIO_AUDIO_SOURCE_2CH_I2S: audio |= STM_AV_SOURCE_2CH_I2S_INPUT; break; case STMHDMIIO_AUDIO_SOURCE_SPDIF: audio |= STM_AV_SOURCE_SPDIF_INPUT; break; case STMHDMIIO_AUDIO_SOURCE_8CH_I2S: audio |= STM_AV_SOURCE_8CH_I2S_INPUT; break; case STMHDMIIO_AUDIO_SOURCE_NONE: break; default: retval = -EINVAL; goto exit; } if(stm_display_output_set_control(dev->hdmi_output, STM_CTRL_AV_SOURCE_SELECT, audio)<0) { if(signal_pending(current)) retval = -ERESTARTSYS; else retval = -EIO; goto exit; } if(stm_display_output_get_control(dev->hdmi_output, STM_CTRL_AV_SOURCE_SELECT, &val)<0) { if(signal_pending(current)) retval = -EINTR; else retval = -EIO; goto exit; } if(val != audio) retval = -EINVAL; break; } case STMHDMIIO_SET_AUDIO_TYPE: { unsigned long val; if(stm_display_output_set_control(dev->hdmi_output, STM_CTRL_HDMI_AUDIO_OUT_SELECT, arg)<0) { if(signal_pending(current)) retval = -ERESTARTSYS; else retval = -EIO; goto exit; } if(stm_display_output_get_control(dev->hdmi_output, STM_CTRL_HDMI_AUDIO_OUT_SELECT, &val)<0) { if(signal_pending(current)) retval = -EINTR; else retval = -EIO; goto exit; } if(val != arg) retval = -EINVAL; break; } case STMHDMIIO_SET_OVERSCAN_MODE: { if(arg > STMHDMIIO_SCAN_UNDERSCANNED) { retval = -EINVAL; goto exit; } if(stm_display_output_set_control(dev->hdmi_output, STM_CTRL_HDMI_OVERSCAN_MODE, arg)<0) { if(signal_pending(current)) retval = -ERESTARTSYS; else retval = -EIO; } break; } case STMHDMIIO_SET_CONTENT_TYPE: { ULONG val = 0; if(arg > STMHDMIIO_CE_CONTENT) { retval = -EINVAL; goto exit; } /* * Map the argument to infoframe bits IT|CN1|CN0 */ switch(arg) { case STMHDMIIO_CE_CONTENT: val = 0; break; default: val = arg | (1L<<2); break; } if(stm_display_output_set_control(dev->hdmi_output, STM_CTRL_HDMI_CONTENT_TYPE, val)<0) { if(signal_pending(current)) retval = -ERESTARTSYS; else retval = -EIO; } break; } case STMHDMIIO_SET_EDID_MODE_HANDLING: { unsigned long flags; if(arg > STMHDMIIO_EDID_NON_STRICT_MODE_HANDLING) { retval = -EINVAL; goto exit; } dev->non_strict_edid_semantics = arg; spin_lock_irqsave(&dev->spinlock, flags); if(dev->status != STM_DISPLAY_DISCONNECTED) { dev->status = STM_DISPLAY_NEEDS_RESTART; dev->status_changed = 1; wake_up (&dev->status_wait_queue); } spin_unlock_irqrestore(&dev->spinlock, flags); break; } case STMHDMIIO_SET_HOTPLUG_MODE: { if(arg > STMHDMIIO_HPD_STOP_IF_NECESSARY) { retval = -EINVAL; goto exit; } dev->hotplug_mode = arg; break; } case STMHDMIIO_SET_CEA_MODE_SELECTION: { if(arg > STMHDMIIO_CEA_MODE_FROM_EDID_ASPECT_RATIO) { retval = -EINVAL; goto exit; } switch(arg) { case STMHDMIIO_CEA_MODE_FROM_EDID_ASPECT_RATIO: dev->cea_mode_from_edid = 1; /* * In case the display is already running, change the mode to whatever * the EDID says. Note that if the EDID had bad data we default to * 16:9. */ arg = (dev->edid_info.tv_aspect == STM_WSS_4_3)?STMHDMIIO_CEA_MODE_4_3:STMHDMIIO_CEA_MODE_16_9; break; default: dev->cea_mode_from_edid = 0; break; } if(stm_display_output_set_control(dev->hdmi_output, STM_CTRL_HDMI_CEA_MODE_SELECT, arg)<0) { if(signal_pending(current)) retval = -ERESTARTSYS; else retval = -EIO; } break; } case STMHDMIIO_SET_SAFE_MODE_PROTOCOL: { unsigned long flags; if(dev->hdmi_safe_mode == arg) goto exit; dev->hdmi_safe_mode = arg; spin_lock_irqsave(&dev->spinlock, flags); if(dev->status != STM_DISPLAY_DISCONNECTED) { dev->status = STM_DISPLAY_NEEDS_RESTART; dev->status_changed = 1; wake_up (&dev->status_wait_queue); } spin_unlock_irqrestore(&dev->spinlock, flags); break; } default: retval = -ENOTTY; } exit: mutex_unlock(&dev->lock); return retval; }
void setup_analogue_voltages(stm_display_output_t *pOutput) { #if defined(CONFIG_STB7100) || defined(CONFIG_STB7109) #if defined(CONFIG_MB602) stm_display_output_set_control(pOutput, STM_CTRL_DAC123_MAX_VOLTAGE, 1402); stm_display_output_set_control(pOutput, STM_CTRL_DAC456_MAX_VOLTAGE, 1402); #else stm_display_output_set_control(pOutput, STM_CTRL_DAC123_MAX_VOLTAGE, 1409); stm_display_output_set_control(pOutput, STM_CTRL_DAC456_MAX_VOLTAGE, 1409); #endif #endif #if defined(CONFIG_MB671) stm_display_output_set_control(pOutput, STM_CTRL_DAC123_MAX_VOLTAGE, 1350); stm_display_output_set_control(pOutput, STM_CTRL_DAC456_MAX_VOLTAGE, 1350); #endif #if defined(CONFIG_MB618) stm_display_output_set_control(pOutput, STM_CTRL_DAC123_MAX_VOLTAGE, 1360); /* * The following is for the CVBS phono output with Jumper 38 set to the 2-3 * position. For some reason there is an op-amp on this path which one assumes * is the reason why set such an add value for the voltage range. */ stm_display_output_set_control(pOutput, STM_CTRL_DAC456_MAX_VOLTAGE, 1600); #endif #if defined(CONFIG_STI7141) || defined(CONFIG_MB680) || defined(CONFIG_MB796) || defined(CONFIG_MB837) stm_display_output_set_control(pOutput, STM_CTRL_DAC123_MAX_VOLTAGE, 1360); stm_display_output_set_control(pOutput, STM_CTRL_DAC456_MAX_VOLTAGE, 1360); #endif #if defined(CONFIG_SDK7105) stm_display_output_set_control(pOutput, STM_CTRL_DAC123_MAX_VOLTAGE, 1320); stm_display_output_set_control(pOutput, STM_CTRL_DAC456_MAX_VOLTAGE, 1320); #endif #if defined(CONFIG_MB837) /* * An unusual one this, the HD DACs are giving much higher voltages than * normal, and different to the SD DACs. */ stm_display_output_set_control(pOutput, STM_CTRL_DAC123_MAX_VOLTAGE, 1490); stm_display_output_set_control(pOutput, STM_CTRL_DAC456_MAX_VOLTAGE, 1370); #endif }