int proc_hdmi_output_write(struct file *file, const char __user *buf,
                           unsigned long count, void *data)
{
	char 		*page;
	ssize_t 	ret = -ENOMEM;
	struct stmfbio_output_configuration outputConfig = {0};
	struct stmfb_info *info = NULL;

	char* myString = kmalloc(count + 1, GFP_KERNEL);

	printk("%s %ld - ", __FUNCTION__, count);

	mutex_lock (&(ProcDeviceContext->DvbContext->Lock));

	page = (char *)__get_free_page(GFP_KERNEL);
	if (page) 
	{
		ret = -EFAULT;
		if (copy_from_user(page, buf, count))
			goto out;

		strncpy(myString, page, count);
		myString[count] = '\0';

		printk("%s\n", myString);
		
		outputConfig.outputid = 1;
		info = stmfb_get_fbinfo_ptr();
		stmfb_get_output_configuration(&outputConfig, info);

		outputConfig.caps = 0;
		outputConfig.activate = STMFBIO_ACTIVATE_IMMEDIATE;
		outputConfig.analogue_config = 0;

		outputConfig.caps |= STMFBIO_OUTPUT_CAPS_HDMI_CONFIG;

		if (!strncmp("off", myString, count))
		{
			outputConfig.hdmi_config |= STMFBIO_OUTPUT_HDMI_DISABLED;
		}
		else if (!strncmp("on", myString, count))
		{
			outputConfig.hdmi_config &= ~STMFBIO_OUTPUT_HDMI_DISABLED;
		}

		stmfb_set_output_configuration(&outputConfig, info);

		/* always return count to avoid endless loop */
		ret = count;
	}
	
out:
	free_page((unsigned long)page);
	kfree(myString);
	mutex_unlock (&(ProcDeviceContext->DvbContext->Lock));
	return ret;
}
示例#2
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;
}
示例#3
0
int proc_video_hdmi_colorspace_write(struct file *file, const char __user *buf, unsigned long count, void *data)
{
	char *page;
	char *myString;
	ssize_t ret = -ENOMEM;
#ifdef VERY_VERBOSE
	printk("%s %ld - ", __FUNCTION__, count);
#endif
	page = (char *)__get_free_page(GFP_KERNEL);
	if (page)
	{
		struct stmfb_info *info = stmfb_get_fbinfo_ptr();
		struct stmfbio_output_configuration outputConfig;
		int err = 0;
		//int alpha = 0;
		int hdmi_colour = 0;
		ret = -EFAULT;
		if (copy_from_user(page, buf, count))
			goto out;
		myString = (char *) kmalloc(count + 1, GFP_KERNEL);
		strncpy(myString, page, count);
		myString[count] = '\0';
#ifdef VERY_VERBOSE
		printk("%s\n", myString);
#endif
		//sscanf(myString, "%d", &alpha);
		//0rgb 1yuv 2422
		if (strncmp("hdmi_rgb", page, count - 1) == 0)
		{
			hdmi_colour = 0;
		}
		else if (strncmp("hdmi_yuv", page, count - 1) == 0)
		{
			hdmi_colour = 1;
		}
		else if (strncmp("hdmi_422", page, count - 1) == 0)
		{
			hdmi_colour = 2;
		}
		outputConfig.outputid = 1;
		stmfb_get_output_configuration(&outputConfig, info);
		outputConfig.caps = 0;
		outputConfig.activate = 0; //STMFBIO_ACTIVATE_IMMEDIATE;
		outputConfig.caps |= STMFBIO_OUTPUT_CAPS_HDMI_CONFIG;
		outputConfig.hdmi_config &= ~(STMFBIO_OUTPUT_HDMI_YUV | STMFBIO_OUTPUT_HDMI_422);
		switch (hdmi_colour)
		{
			case 1:
				outputConfig.hdmi_config |= STMFBIO_OUTPUT_HDMI_YUV;
				break;
			case 2:
				outputConfig.hdmi_config |= (STMFBIO_OUTPUT_HDMI_YUV | STMFBIO_OUTPUT_HDMI_422);
				break;
			default:
				break;
		}
		err = stmfb_set_output_configuration(&outputConfig, info);
		//if(ioctl(fbfd, STMFBIO_SET_OUTPUT_CONFIG, &outputConfig)<0)
		//perror("setting output configuration failed");
		kfree(myString);
	}
	ret = count;
out:
	free_page((unsigned long)page);
	return ret;
}
示例#4
0
int proc_avs_0_colorformat_write(struct file *file, const char __user *buf,
								 unsigned long count, void *data)
{
	char *page;
	char *myString;
	ssize_t ret = -ENOMEM;
#ifdef VERY_VERBOSE
	printk("%s %ld - ", __FUNCTION__, count);
#endif
	page = (char *)__get_free_page(GFP_KERNEL);
	if (page)
	{
		struct stmfb_info *info = stmfb_get_fbinfo_ptr();
		struct stmfbio_output_configuration outputConfig;
		int err = 0;
		int alpha = 0;
		int hdmi_colour = 0;
		int scart_colour = 0;
		int hdmi0scart1yuv2 = 1;
		ret = -EFAULT;
		if (copy_from_user(page, buf, count))
			goto out;
		myString = (char *) kmalloc(count + 1, GFP_KERNEL);
		strncpy(myString, page, count);
		myString[count] = '\0';
#ifdef VERY_VERBOSE
		printk("%s\n", myString);
#endif
		sscanf(myString, "%d", &alpha);
//0rgb 1yuv 2422
		if (strncmp("hdmi_rgb", page, count - 1) == 0)
		{
			hdmi_colour = 0;
			hdmi0scart1yuv2 = 0;
		}
		else if (strncmp("hdmi_yuv", page, count - 1) == 0)
		{
			hdmi_colour = 1;
			hdmi0scart1yuv2 = 0;
		}
		else if (strncmp("hdmi_422", page, count - 1) == 0)
		{
			hdmi_colour = 2;
			hdmi0scart1yuv2 = 0;
		}
		else if (strncmp("rgb", page, count - 1) == 0)
		{
			scart_colour = SAA_MODE_RGB;
			hdmi0scart1yuv2 = 1;
		}
		else if (strncmp("cvbs", page, count - 1) == 0)
		{
			scart_colour = SAA_MODE_FBAS;
			hdmi0scart1yuv2 = 1;
		}
		else if (strncmp("svideo", page, count - 1) == 0)
		{
			scart_colour = SAA_MODE_SVIDEO;
			hdmi0scart1yuv2 = 1;
		}
		else if (strncmp("yuv", page, count - 1) == 0)
		{
			hdmi0scart1yuv2 = 2;
		}
		if (hdmi0scart1yuv2 == 0)
		{
			outputConfig.outputid = 1;
			stmfb_get_output_configuration(&outputConfig, info);
			outputConfig.caps = 0;
			outputConfig.activate = 0; //STMFBIO_ACTIVATE_IMMEDIATE;
			outputConfig.caps |= STMFBIO_OUTPUT_CAPS_HDMI_CONFIG;
			outputConfig.hdmi_config &= ~(STMFBIO_OUTPUT_HDMI_YUV | STMFBIO_OUTPUT_HDMI_422);
			switch (hdmi_colour)
			{
				case 1:
					outputConfig.hdmi_config |= STMFBIO_OUTPUT_HDMI_YUV;
					break;
				case 2:
					outputConfig.hdmi_config |= (STMFBIO_OUTPUT_HDMI_YUV | STMFBIO_OUTPUT_HDMI_422);
					break;
				default:
					break;
			}
			err = stmfb_set_output_configuration(&outputConfig, info);
		}
		else if (hdmi0scart1yuv2 == 1)
		{
			avs_command_kernel(SAAIOSMODE, (void *) scart_colour);
			outputConfig.outputid = 1;
			stmfb_get_output_configuration(&outputConfig, info);
			outputConfig.caps = 0;
			outputConfig.activate = 0; //STMFBIO_ACTIVATE_IMMEDIATE;
			outputConfig.caps |= STMFBIO_OUTPUT_CAPS_ANALOGUE_CONFIG;
			outputConfig.analogue_config = 0;
			switch (scart_colour)
			{
				case SAA_MODE_RGB:
					outputConfig.analogue_config |= (STMFBIO_OUTPUT_ANALOGUE_RGB | STMFBIO_OUTPUT_ANALOGUE_CVBS);
					break;
				case SAA_MODE_FBAS:
					outputConfig.analogue_config |= STMFBIO_OUTPUT_ANALOGUE_CVBS;
					break;
				case SAA_MODE_SVIDEO:
					outputConfig.analogue_config |= STMFBIO_OUTPUT_ANALOGUE_YC;
					break;
				default:
					break;
			}
			err = stmfb_set_output_configuration(&outputConfig, info);
			if (err != 0)
			{
				printk("SET SCART COLOR - %ld - ", count);
			}
		}
		else
		{
			outputConfig.outputid = 1;
			stmfb_get_output_configuration(&outputConfig, info);
			outputConfig.caps = 0;
			outputConfig.activate = 0; //STMFBIO_ACTIVATE_IMMEDIATE;
			outputConfig.caps |= STMFBIO_OUTPUT_CAPS_ANALOGUE_CONFIG;
			outputConfig.analogue_config = 0;
			outputConfig.analogue_config |= STMFBIO_OUTPUT_ANALOGUE_YPrPb;
			err = stmfb_set_output_configuration(&outputConfig, info);
			if (err != 0)
			{
				printk("SET SCART COLOR - %ld - ", count);
			}
		}
		//if(ioctl(fbfd, STMFBIO_SET_OUTPUT_CONFIG, &outputConfig)<0)
		//perror("setting output configuration failed");
		kfree(myString);
	}
	ret = count;
out:
	free_page((unsigned long)page);
	return ret;
}
示例#5
0
int proc_avs_0_input_write(struct file *file, const char __user *buf,
						   unsigned long count, void *data)
{
	char *page;
	char *myString;
	ssize_t ret = -ENOMEM;
	/* int result; */
#if defined(ADB_BOX)
	struct stmfbio_output_configuration outputConfig;
	struct stmfb_info *info = stmfb_get_fbinfo_ptr();
	int err;
	outputConfig.outputid = 1;
	stmfb_get_output_configuration(&outputConfig, info);
	outputConfig.caps = 0;
	outputConfig.activate = 0;//STMFBIO_ACTIVATE_IMMEDIATE;
	outputConfig.analogue_config = 0;
	outputConfig.caps |= STMFBIO_OUTPUT_CAPS_HDMI_CONFIG;
#endif
#ifdef VERY_VERBOSE
	printk("%s %ld - ", __FUNCTION__, count);
#endif
	page = (char *)__get_free_page(GFP_KERNEL);
	if (page)
	{
		ret = -EFAULT;
		if (copy_from_user(page, buf, count))
			goto out;
		myString = (char *) kmalloc(count + 1, GFP_KERNEL);
		strncpy(myString, page, count);
		myString[count] = '\0';
#ifdef VERY_VERBOSE
		printk("%s\n", myString);
#endif
		if (!strncmp("encoder", myString, count - 1))
		{
			avs_command_kernel(SAAIOSSRCSEL, SAA_SRC_ENC);
			// Note: Volumne is not changed directly but by using the MIXER instead of the AVS.
			// So this should always be set to the maximum
#if defined(UFS910) \
 || defined(ADB_BOX)
			avs_command_kernel(AVSIOSVOL, (void *) 31);
#else
			avs_command_kernel(AVSIOSVOL, (void *) 0);
#endif
#if defined(ADB_BOX)
			avs_command_kernel(SAAIOSWSS, (void *) SAA_WSS_43F);
			outputConfig.hdmi_config &= ~STMFBIO_OUTPUT_HDMI_DISABLED;
#endif
			current_input = ENCODER;
		}
		if (!strncmp("scart", myString, count - 1))
		{
			avs_command_kernel(SAAIOSSRCSEL, (void *) SAA_SRC_SCART);
			avs_command_kernel(AVSIOSVOL, (void *) current_volume);
#if defined(ADB_BOX)
			avs_command_kernel(SAAIOSWSS, (void *) SAA_WSS_OFF);
			outputConfig.hdmi_config |= STMFBIO_OUTPUT_HDMI_DISABLED;
#endif
			current_input = SCART;
		}
#if defined(ADB_BOX)
		err = stmfb_set_output_configuration(&outputConfig, info);
		if (err != 0)
		{
			printk("HDMI Config Disabled - Failed !!!!!!!!!!");
		}
#endif
		kfree(myString);
		//result = sscanf(page, "%3s %3s %3s %3s %3s", s1, s2, s3, s4, s5);
	}
	ret = count;
out:
	free_page((unsigned long)page);
	return ret;
}
示例#6
0
文件: stmfb.c 项目: Firmeware/driver
/*
 *  stmfb_createfb
 *  Create framebuffer related state and register with upper layers
 */
static int stmfb_createfb(struct stmfb_info *i, int display, const char *name)
{
  int ret;
  unsigned long nPages;
  int fb_registered = 0;
  const struct stmcore_display_pipeline_data * const pd =
    *((struct stmcore_display_pipeline_data **) i->platformDevice->dev.platform_data);

  DPRINTK("\n");

  /*
   * Copy all available display modes into the modelist, before we parse
   * the module parameters to get the default mode.
   */
  stmfb_enumerate_modes(i);

  /*
   * Need to set the framebuffer operation table and get hold of the display
   * plane before parsing the module parameters so fb_find_mode can work.
   */
  i->info.fbops = &stmfb_ops;

  if((ret = stmfb_parse_module_parameters(i, display)) < 0)
    goto failed0;

  /* can create blitter only after module parameters have been parsed */
  if((ret = stmfb_probe_get_blitter(i,pd))<0)
    goto failed0;

  nPages = (i->ulFBSize + PAGE_SIZE - 1) / PAGE_SIZE;

  i->FBPart = bpa2_find_part ("bigphysarea");
  i->ulPFBBase = i->FBPart ? bpa2_alloc_pages (i->FBPart, nPages, 0, GFP_KERNEL)
                           : 0;
  if (!i->ulPFBBase)
  {
    printk(KERN_WARNING "Failed to allocate fb%d memory, requested size = %lu\n",display, i->ulFBSize);
    ret = -ENOMEM;
    goto failed0;
  }

  /* try to allocate memory from BPA2 as additional memory for graphics
     operations. Basically, this is not vital, but driver loading will still
     fail if an auxsize has been specified in the module parameters which can
     not be satisfied, either because no BPA2 partition 'gfx-memory' exists,
     or if it's not large enough for the given auxsize. */
  /* Please note that due to hardware limitations, this can actually be a bit
     complex (2 & 3):
     1) we look for partitions labelled 'gfx-memory-[0...x]', each of which
        should be 64MB in size and be aligned to a 64MB bank. This makes the
        process quite easy for us.
     2) Failing that, we try to use a partition labelled 'gfx-memory'. Now we
        have to make sure ourselves that each allocation does not cross a 64MB
        bank boundary.
     3) Failing that, too, or in case the 'gfx-memory' partition not being
        large enough to accomodate for the amount of gfx memory requested in
        the module options, we will do the same but this time use the
        'bigphysarea' partition. */
  /* So, either one can configure several 'gfx-memory-%d' partitions
     (preferred, to have maximum control over placement of gfx memory), just
     use one large 'gfx-memory' partition, or configure nothing at all and be
     limited to 'bigphysarea' memory.
     The combined memory of all the allocations will be made available to
     DirectFB. */
  /* FIXME: this code is way too complex! */
#define MEMORY64MB_SIZE      (1<<26)
  if (i->AuxSize[0])
  {
    /* aux memory was requested */
    unsigned int       idx;        /* index into i->AuxPart[] */
    /* order of partnames is important here! */
    static const char *partnames[] = { "gfx-memory-%d", "gfx-memory", "bigphysarea" };
    unsigned int       partnameidx /* index into partnames[] */,
                       partidx     /* index in case of 'gfx-memory-%d' */;
    char               partname[14]; /* real name in case of 'gfx-memory-%d' */
    struct bpa2_part  *part;
    unsigned long      still_needed = i->AuxSize[0];

    unsigned long      this_alloc;
    int                alignment;

    partidx = 0;
    /* find a partition suitable for us, in the preferred order, as outlined
       above */
    for (partnameidx = 0; partnameidx < ARRAY_SIZE (partnames); ++partnameidx)
    {
      sprintf (partname, partnames[partnameidx], 0);
      part = bpa2_find_part (partname);
      if (part)
        break;
    }

    if (!part)
    {
      printk (KERN_ERR "no BPA2 partitions found for auxmem!\n");
      goto failed_bigphys;
    }

    idx = 0;

restart:
    if (still_needed >= MEMORY64MB_SIZE)
    {
      /* we first try to satisfy from a 64MB aligned region */
      this_alloc = MEMORY64MB_SIZE;
      /* don't request a specific alignment if individual 'gfx-memory-%d'
         partitions are configured in the kernel */
      alignment  = (partnameidx == 0) ? 0 : MEMORY64MB_SIZE / PAGE_SIZE;
    }
    else
    {
      /* if requested size is < 64MB, we are optimistic and hope it will
         fit into one 64MB bank without alignment restrictions. This
         doesn't mean we will be happy with a region crossing that
         boundary, i.e. we will still make sure all restrictions are met.
         We are really being just optimistic here. */
      this_alloc = still_needed;
      alignment  = 0;
    }

    while (part && idx < ARRAY_SIZE (i->AuxPart) && still_needed)
    {
      int           this_pages;
      unsigned long base;

      printk (KERN_INFO "trying to alloc %lu bytes (align: %.4x, still needed:"
                        " %lu) from '%s' for GFX%d auxmem\n",
              this_alloc, alignment, still_needed, partname, display);

      this_pages = (this_alloc + PAGE_SIZE - 1) / PAGE_SIZE;
      base = bpa2_alloc_pages (part, this_pages, alignment, GFP_KERNEL);
      if (base)
      {
        /* make sure it doesn't cross a 64MB boundary. At some point we will
           be using the new BPA2 allocator API... */
        if ((base & ~(MEMORY64MB_SIZE - 1)) != ((base + this_alloc - 1) & ~(MEMORY64MB_SIZE - 1)))
        {
          unsigned long topAddress;

          printk ("%s: %8.lx + %lu (%d pages) crosses a 64MB boundary, retrying!\n",
                  __FUNCTION__, base, this_alloc, this_pages);

          /* free and try a new reservation with different attributes,
             hoping nobody requests bpa2 memory in between... */
          bpa2_free_pages (part, base);

          if (partnameidx == 0)
          {
            /* if we have 'gfx-memory-%d' partitions, try the next one */
            /* Getting here doesn't neccessarily mean there is an error in
               the BPA2 partition definition. This can happen if e.g. two
               framebuffers are configured and the auxmem size requested is
               larger but not a multiple of 64MB (since we are optimistic and
               try to re-use partially used partitions), so don't be tempted
               to put a WARN_ON() here! */
            sprintf (partname, partnames[partnameidx], ++partidx);
            part = bpa2_find_part (partname);
            continue;
          }

          if (still_needed == this_alloc && alignment == 0)
          {
            /* this can only happen on the last chunk of memory needed. So
               we first try to fit it into its own region.
               I.e. we first try to put the last chunk into a partly used
               bank. If we succeed, but the chunk now spans a boundary
               (which gets us here), we try to put it into its own
               bank. If that fails, too, we will come back again (this
               time with alignment == 1) and split the chunk into two. */
            alignment = MEMORY64MB_SIZE / PAGE_SIZE;
            continue;
          }

          /* standard case, allocate up to the end of current 64MB bank,
             effectively splitting the current chunk into two. */
#define _ALIGN_UP(addr,size)    (((addr)+((size)-1))&(~((size)-1)))
          topAddress = _ALIGN_UP (base, MEMORY64MB_SIZE);
          this_alloc = topAddress - base;
          this_pages = (this_alloc + PAGE_SIZE - 1) / PAGE_SIZE;

          /* alignment should be 0 or 1 here */
          WARN_ON (alignment != 0
                   && alignment != 1);
          base = bpa2_alloc_pages (part, this_pages, alignment, GFP_KERNEL);
          if (!base)
          {
            /* shouldn't happen here, since we just moments ago suceeded in
               allocating even more memory than now, so we don't know what
               to do and kindof panic ...*/
            break;
          }
        }

        /* we now have found a more or less nice place to chill. */
        i->AuxPart[idx] = part;
        i->AuxBase[idx] = base;
        i->AuxSize[idx] = this_alloc;
        ++idx;

        still_needed -= this_alloc;

        printk (KERN_INFO "success: base: %.8lx, still needed: %lu\n",
                base, still_needed);

        if (still_needed >= MEMORY64MB_SIZE)
        {
          /* we first try to satisfy from a 64MB aligned region */
          this_alloc = MEMORY64MB_SIZE;
          alignment  = (partnameidx == 0) ? 0 : MEMORY64MB_SIZE / PAGE_SIZE;
        }
        else
        {
          /* if requested size is < 64MB we are on the last chunk of memory
             blocks. We are otimistic and hope it will fit into a possibly
             already partly used 64MB bank without alignment restrictions,
             i.e. we hope it will not span a 64MB boundary. If that's not
             the case, we will again use an alignment of 64MB, so as to
             reduce scattering of the auxmem chunks. */
          this_alloc = still_needed;
          alignment  = 0;

          /* if using 'gfx-memory-%d' partitions, try to share the last
             chunk with another chunk (in a possibly partly used
             partition). */
          if (partnameidx == 0)
            partidx = -1;
        }

        if (partnameidx == 0)
        {
          /* in case we are using 'gfx-memory-%d' as partition name, make
             sure we advance to the next partition */
          sprintf (partname, partnames[partnameidx], ++partidx);
          part = bpa2_find_part (partname);
        }
      }
      else
      {
        if (alignment > 1)
        {
          if (still_needed == this_alloc)
            /* make sure not to get into an endless loop which would be
               switching around the alignment all the time. */
            alignment = 1;
          else
            /* try again with different alignment rules */
            alignment = 0;
        }
        else
        {
          /* failed: couldn't allocate any memory at all, even without any
             alignment restrictions.
             1) In case there are 'gfx-memory-%d' partitions, we advance
                to the next one.
             2) In case we had been using 'gfx-memory' as partition name,
                we now try 'bigphysarea'*/
          if (partnameidx == 0)
          {
            /* use next 'gfx-memory-%d' partition */
            BUG_ON (strcmp (partnames[partnameidx], "gfx-memory-%d"));
            sprintf (partname, partnames[partnameidx], ++partidx);
            part = bpa2_find_part (partname);
          }
          else if (partnameidx == 1)
          {
            /* advance from 'gfx-memory' to 'bigphysarea' partition name */
            BUG_ON (strcmp (partnames[partnameidx], "gfx-memory"));
            sprintf (partname, partnames[++partnameidx], 0);
            BUG_ON (strcmp (partnames[partnameidx], "bigphysarea"));
            part = bpa2_find_part (partname);
            goto restart;
          }
          else
            /* that's it, there are no partitions left to check for auxmem */
            break;
        }
      }
    }

    if (still_needed)
    {
      /* not enough chill space configured for BPA2 */
      printk (KERN_WARNING "Failed to allocate enough fb%d auxmem "
                           "(still need %lu bytes)\n",
              display, still_needed);
      ret = -ENOMEM;
      goto failed_auxmem;
    }
  }

  if(stm_display_plane_connect_to_output(i->pFBPlane, i->pFBMainOutput) < 0)
  {
    printk(KERN_ERR "fb%d display cannot be connected to display output pipeline, this is very bad!\n",display);
    ret = -EIO;
    goto failed_auxmem;
  }

  if(stm_display_plane_lock(i->pFBPlane) < 0)
  {
    printk(KERN_WARNING "fb%d display plane may already be in use by another driver\n",display);
    ret = -EBUSY;
    goto failed_auxmem;
  }

  i->main_config.activate = STMFBIO_ACTIVATE_IMMEDIATE;
  if(stmfb_set_output_configuration(&i->main_config,i)<0)
  {
    printk(KERN_WARNING "fb%d main output configuration is unsupported\n",display);
    ret = -EINVAL;
    goto failed_auxmem;
  }

  /*
   * Get the framebuffer layer default extended var state and capabilities
   */
  i->current_var_ex.layerid = 0;

  if((ret = stmfb_encode_var_ex(&i->current_var_ex, i)) < 0)
  {
    printk(KERN_WARNING "fb%d failed to get display plane's extended capabilities\n",display);
    goto failed_auxmem;
  }

  /* Setup the framebuffer info for registration */
  i->info.screen_base = ioremap_nocache(i->ulPFBBase,i->ulFBSize);
  i->info.flags       = FBINFO_DEFAULT |
                        FBINFO_PARTIAL_PAN_OK |
                        FBINFO_HWACCEL_YPAN;

  strcpy(i->info.fix.id, name);  /* identification string */

  i->info.fix.smem_start  = i->ulPFBBase;                /* Start of frame buffer mem (physical address)               */
  i->info.fix.smem_len    = i->ulFBSize;                 /* Length of frame buffer mem as the device sees it           */
  i->info.fix.mmio_start  = pd->mmio;                    /* memory mapped register access     */
  i->info.fix.mmio_len    = pd->mmio_len;                /* Length of Memory Mapped I/O       */
  i->info.fix.type        = FB_TYPE_PACKED_PIXELS;       /* see FB_TYPE_*                     */
  i->info.fix.type_aux    = 0;                           /* Interleave for interleaved Planes */
  i->info.fix.xpanstep    = 0;                           /* zero if no hardware panning       */
  i->info.fix.ypanstep    = 1;                           /* zero if no hardware panning       */
  i->info.fix.ywrapstep   = 0;                           /* zero if no hardware ywrap         */

  i->info.pseudo_palette = &i->pseudo_palette;

  if(fb_alloc_cmap(&i->info.cmap, 256, 1)<0)
  {
    printk(KERN_ERR "fb%d unable to allocate colour map\n",display);
    ret = -ENOMEM;
    goto failed_ioremap;
  }

  if(i->info.cmap.len != 256)
  {
    printk(KERN_ERR "fb%d WTF colour map length is wrong????\n",display);
  }

  if (register_framebuffer(&i->info) < 0)
  {
    printk(KERN_ERR "fb%d register =_framebuffer failed!\n",display);
    ret = -ENODEV;
    goto failed_cmap;
  }

  /*
   * If there was no console activated on the registered framebuffer, we have
   * to force the display mode be updated. This sequence is cribbed from the
   * matroxfb driver.
   */
  if(!i->current_videomode_valid)
  {
    i->info.var.activate |= FB_ACTIVATE_FORCE;
    if((ret = fb_set_var(&i->info, &i->info.var))<0)
    {
      printk(KERN_WARNING "fb%d failed to set default display mode, display pipeline may already be in use\n",display);
      goto failed_register;
    }
  }

//#if (defined(UFS912) || defined(HS7110) || defined(HS7119) || defined(HS7420) || defined(HS7429) || defined(HS7810A) || defined(HS7819) || defined(ATEMIO520) || defined(ATEMIO530) || defined(SPARK) || defined(AT7500)) && defined(__TDT__)
  // WORKAROUND: Clear the framebuffer 
  memset(i->info.screen_base, 0x00, i->ulFBSize);
//#endif

  stmfb_init_class_device(i);

  DPRINTK("out\n");

  return 0;

failed_register:
  fb_registered = 1;
  unregister_framebuffer (&i->info);

failed_cmap:
  fb_dealloc_cmap (&i->info.cmap);

failed_ioremap:
  iounmap (i->info.screen_base);
  i->info.screen_base = NULL;

failed_auxmem:
  stmfb_destroy_auxmem (i);

failed_bigphys:
  bpa2_free_pages (i->FBPart, i->ulPFBBase);
  i->ulPFBBase = 0;
  i->FBPart = NULL;

failed0:
  if (!fb_registered)
    /* unregister_framebuffer() does fb_destroy_modelist() for us, so don't
       destroy it twice! */
    fb_destroy_modelist (&i->info.modelist);

  return ret;
}