Example #1
0
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;
}
Example #2
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;

}
Example #3
0
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;
}
Example #4
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;
}
Example #5
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;
}
Example #6
0
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;
}
Example #8
0
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;
}
Example #9
0
/******************************************************************************
 * 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);
  }
}
Example #10
0
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

}