Beispiel #1
0
static int stmfbio_set_blitter_palette(struct stmfb_info* i, u_long arg)
{
  DPRINTK("palette: copying to i->pBlitterCLUT = %p.\n",i->pBlitterCLUT);

  if (!i->pBlitter || !i->pBlitterCLUT)
    return -ENODEV;

  if(down_interruptible(&i->framebufferLock))
    return -ERESTARTSYS;

  if(stm_display_blitter_sync(i->pBlitter)<0)
  {
    DPRINTK("palette: sync blitter failed\n");
    up(&i->framebufferLock);
    return -EINTR;
  }

  if(copy_from_user(i->pBlitterCLUT,(void*)(arg+offsetof(STMFBIO_PALETTE,entries)),sizeof(unsigned long)*256))
  {
    DPRINTK("failed to copy palette from user data.\n");
    up(&i->framebufferLock);
    return -EFAULT;
  }

  DPRINTK("palette: [ 0x%lx, 0x%lx, 0x%lx, 0x%lx ]\n",i->pBlitterCLUT[0],i->pBlitterCLUT[1],i->pBlitterCLUT[2],i->pBlitterCLUT[3]);

  up(&i->framebufferLock);
  return 0;
}
Beispiel #2
0
static int __exit stmfb_remove(struct platform_device *pdev)
{
  struct stmfb_info *i = (struct stmfb_info *)platform_get_drvdata(pdev);
  struct stmcore_display_pipeline_data *pd = *((struct stmcore_display_pipeline_data **)pdev->dev.platform_data);

  DPRINTK("\n");

  if(!i)
    return 0;

  if(i->pBlitter)
    stm_display_blitter_sync(i->pBlitter);

  stmfb_destroyfb(i);
  stmfb_cleanup_info(i);

  platform_set_drvdata(pdev,NULL);

  module_put(pd->owner);

  return 0;
}
Beispiel #3
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;
}
Beispiel #4
0
static int stmfb_suspend(struct platform_device *pdev, pm_message_t state)
{
  struct stmfb_info *i = (struct stmfb_info *)platform_get_drvdata(pdev);

  DPRINTK("\n");

  if(!i)
    return 0;

  if (state.event == pdev->dev.power.power_state.event)
    return 0;

  acquire_console_sem();

  if(down_interruptible(&i->framebufferLock))
  {
    release_console_sem();
    return -EINTR;
  }

  if(i->pBlitter)
  {
    if(stm_display_blitter_sync(i->pBlitter)<0)
    {
      release_console_sem();
      up(&i->framebufferLock);
      return -EINTR;
    }
  }

  /*
   * Suspend the main output first (there must be one!) which will stop the
   * timing generator, hence any more vsync interrupts.
   */
  if(i->pFBMainOutput)
    stm_display_output_suspend(i->pFBMainOutput);

  if(i->pFBDVO)
    stm_display_output_suspend(i->pFBDVO);

  /*
   * HDMI is different, we need to stop it completely, which will force
   * the display state to NEEDS_RESTART. Once we resume the main output and
   * get a new VSYNC interrupt the ISR will spot this state change and signal
   * the HDMI thread which will look to see if the connected device has changed
   * (i.e. someone plugged in a different TV) while we were suspended and bring
   * the HDMI output back up again (if required at all) in the correct state.
   */
  if(i->hdmi)
    stm_display_output_stop(i->hdmi->hdmi_output);

  /*
   * We release the framebuffer lock here as the fb_set_suspend callbacks
   * might call back into the driver.
   */
  up(&i->framebufferLock);

  fb_set_suspend(&i->info, 1);

  release_console_sem();

  DPRINTK("finished suspending\n");
  return 0;
}