Exemple #1
0
void do_ipp( Connection *conn, int length ) {
  IPP *reply;
  int len=0, pos;

  conn->ipp = ipp_new();
  conn->ipp->data_left = length;

  if( getshort_conn( conn, &conn->ipp->version ) ) {
    if( getshort_conn( conn, &conn->ipp->operation ) ) {
      if( getint_conn( conn, &conn->ipp->request_id ) ) {
        conn->ipp->data_left -= 8;
        process_ipp_tags( conn );
      }
    }
  }
  reply = NULL;
  switch( conn->ipp->operation ) {
    case IPP_GET_PRINTER_ATTR:
      reply = ipp_printer_attrs( conn->ipp );
      break;
    case IPP_GET_JOBS:
      reply = ipp_get_jobs( conn->ipp );
      break;
    case IPP_PRINT_JOB: // Special function
      printf( "Got print request.\n" );
      ipp_print_job( conn, length );
      break;
    case IPP_GET_JOB_ATTR:
      reply = ipp_job_attrs( conn->ipp );
      break;
    default:
      ipp_pretty_print( conn->ipp );
      reply = ipp_new();
      reply->response = IPP_ERR_NOT_FOUND; // No such uri
      reply->version = 256; //IPP 1.0
      reply->request_id = conn->ipp->request_id;
      ipp_add_tag( reply, IPP_TAG_OPERATIONS, NULL, NULL, 0, 0 );
      ipp_copy_tag( reply, conn->ipp, IPP_TAG_OPERATIONS, "attributes-charset" );
      ipp_copy_tag( reply, conn->ipp, IPP_TAG_OPERATIONS, "attributes-natural-language" );
  }
  if( reply ) {
#ifdef IPP_DEBUG
    printf( "Connection descriptor is: %d\n", conn->fd );
#endif
    len = ipp_write( reply, NULL, len );
    pos = sprintf( conn->buffer, "HTTP/1.1 200 OK\r\nContent-Type: application/ipp\r\nContent-Length: %d\r\n\r\n", len );
    ipp_write( reply, conn->buffer + pos, len );
    conn->used = len + pos;
    conn->buf_ptr = 0;
    conn->state = CONN_OUTPUT;
    ipp_free( reply );
  }
}
static irqreturn_t rk29_ipp_irq(int irq,  void *dev_id)
{
	DBG("rk29_ipp_irq %d \n",irq);
	//printk("rk29_ipp_irq %d \n",irq);

#ifdef IPP_TEST
	hw_end = ktime_get();
#endif

	ipp_write(ipp_read(IPP_INT)|0x3c, IPP_INT);
	if(((ipp_read(IPP_INT)>>6)&0x3) !=0)// idle
	{	
		printk("IPP is not idle!\n");
		ipp_soft_reset();
		drvdata->ipp_result =  -EAGAIN;
	}
	
	//interacting with hardware done
	wq_condition = 1;
	
#ifdef IPP_TEST
	irq_start = ktime_get();
#endif

	if(drvdata->issync)//sync
	{
		//wake_up_interruptible_sync(&hw_wait_queue);
		wake_up(&hw_wait_queue);
	}
	else//async
	{
		//power off
		schedule_delayed_work(&drvdata->power_off_work, msecs_to_jiffies(50));
		drvdata->ipp_irq_callback(drvdata->ipp_result);
		
		//In the case of async call ,we wake up the wait queue here
		drvdata->ipp_async_result = drvdata->ipp_result;
		idle_condition = 1;
		wake_up_interruptible_sync(&blit_wait_queue);
	}
	
	
	return IRQ_HANDLED;
}
static void ipp_soft_reset(void)
{
	uint32_t i;
	uint32_t reg;

	ipp_write(1, IPP_SRESET);

	for(i = 0; i < IPP_RESET_TIMEOUT; i++) {
		reg = ipp_read( IPP_SRESET) & 1;

		if(reg == 0)
			break;

		udelay(1);
	}

	if(i == IPP_RESET_TIMEOUT)
		ERR("soft reset timeout.\n");
}
int ipp_blit(const struct rk29_ipp_req *req)
{
	
	uint32_t rotate;
	uint32_t pre_scale	= 0;
	uint32_t post_scale = 0;
	uint32_t pre_scale_w, pre_scale_h;//pre_scale para
	uint32_t post_scale_w = 0x1000;
	uint32_t post_scale_h = 0x1000;
	uint32_t pre_scale_output_w=0, pre_scale_output_h=0;//pre_scale output with&height
	uint32_t post_scale_input_w, post_scale_input_h;//post_scale input width&height
	uint32_t dst0_YrgbMst=0,dst0_CbrMst=0;
	uint32_t ret = 0;
	uint32_t deinterlace_config = 0;
	uint32_t src0_w = req->src0.w;
	uint32_t src0_h = req->src0.h;
	
	//printk("ipp_blit\n");
	if (drvdata == NULL) {			/* [email protected] : check driver is normal or not */
		printk("%s drvdata is NULL, IPP driver probe is fail!!\n", __FUNCTION__);
		return -EPERM;
	}

	drvdata->ipp_result = -1;

	//When ipp_blit_async is called in kernel space req->complete should NOT be NULL, otherwise req->complete should be NULL
	if(req->complete)
	{
		drvdata->ipp_irq_callback = req->complete;
	}
	else
	{
		drvdata->ipp_irq_callback = ipp_blit_complete;
	}

	ret = ipp_check_param(req);
	if(ret ==  -EINVAL)
	{	
		printk("IPP invalid input!\n");
		goto erorr_input;
	}
	
	rotate = req->flag;
	switch (rotate) {
	case IPP_ROT_90:
		//for rotation 90 degree
		DBG("rotate %d, src0.fmt %d",rotate,req->src0.fmt);
		switch(req->src0.fmt)
		{
		case IPP_XRGB_8888:
			dst0_YrgbMst  =  req->dst0.YrgbMst + req->dst0.w*4;
			dst0_CbrMst  = req->dst0.CbrMst;
			break;

		case IPP_RGB_565:
			dst0_YrgbMst  =  req->dst0.YrgbMst +  req->dst0.w*2;
			dst0_CbrMst  = req->dst0.CbrMst;
			break;

		case IPP_Y_CBCR_H1V1:
			dst0_YrgbMst  =  req->dst0.YrgbMst + req->dst0.w;
			dst0_CbrMst   =  req->dst0.CbrMst + req->dst0.w*2;
			break;

		case IPP_Y_CBCR_H2V1:
			dst0_YrgbMst =	req->dst0.YrgbMst + req->dst0.w;
			dst0_CbrMst  =	req->dst0.CbrMst + req->dst0.w*2;
			break;

		case IPP_Y_CBCR_H2V2:
			dst0_YrgbMst = req->dst0.YrgbMst+ req->dst0.w;
			dst0_CbrMst  = req->dst0.CbrMst + req->dst0.w;
			break;

		default:

			break;
		}
	break;

	case IPP_ROT_180:
		//for rotation 180 degree
		DBG("rotate %d, src0.fmt %d",rotate,req->src0.fmt);
		switch(req->src0.fmt)
		{
		case IPP_XRGB_8888:
			dst0_YrgbMst =	req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w*4+req->dst0.w*4;
			dst0_CbrMst  = req->dst0.CbrMst;
			break;

		case IPP_RGB_565:
			dst0_YrgbMst =	req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w*2+req->dst0.w*2;
			dst0_CbrMst  = req->dst0.CbrMst;
			break;

		case IPP_Y_CBCR_H1V1:
			dst0_YrgbMst =	req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w+req->dst0.w;
			dst0_CbrMst  =	req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w*2+req->dst0.w*2;
			break;

		case IPP_Y_CBCR_H2V1:
			dst0_YrgbMst =	req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w+req->dst0.w;
			dst0_CbrMst  =	req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w+req->dst0.w;
			break;

		case IPP_Y_CBCR_H2V2:
			dst0_YrgbMst =	req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w+req->dst0.w;
			dst0_CbrMst  =	req->dst0.CbrMst+((req->dst0.h/2)-1)*req->dst_vir_w+req->dst0.w;
			break;

		default:
			break;
		}
			break;

	case IPP_ROT_270:
		DBG("rotate %d, src0.fmt %d \n",rotate,req->src0.fmt);
		switch(req->src0.fmt)
		{
		case IPP_XRGB_8888:
			dst0_YrgbMst =	req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w*4;
			dst0_CbrMst  = req->dst0.CbrMst;
			break;

		case IPP_RGB_565:
			dst0_YrgbMst =	req->dst0.YrgbMst +(req->dst0.h-1)*req->dst_vir_w*2;
			dst0_CbrMst  = req->dst0.CbrMst;
			break;

		case IPP_Y_CBCR_H1V1:
			dst0_YrgbMst =	req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w;
			dst0_CbrMst  =	req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w*2;
			break;

		case IPP_Y_CBCR_H2V1:
			dst0_YrgbMst =	req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w;
			dst0_CbrMst  =	req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w*2;
			break;

		case IPP_Y_CBCR_H2V2:
			dst0_YrgbMst =	req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w;
			dst0_CbrMst  =	req->dst0.CbrMst+((req->dst0.h/2)-1)*req->dst_vir_w;
			break;

		default:
			break;
		}
		break;

	case IPP_ROT_X_FLIP:
		DBG("rotate %d, src0.fmt %d",rotate,req->src0.fmt);
		switch(req->src0.fmt)
		{
		case IPP_XRGB_8888:
			dst0_YrgbMst =	req->dst0.YrgbMst+req->dst0.w*4;
			dst0_CbrMst  = req->dst0.CbrMst;
			break;

		case IPP_RGB_565:
			dst0_YrgbMst =	req->dst0.YrgbMst+req->dst0.w*2;
			dst0_CbrMst  = req->dst0.CbrMst;
			break;

		case IPP_Y_CBCR_H1V1:
			dst0_YrgbMst =	req->dst0.YrgbMst+req->dst0.w;
			dst0_CbrMst  =	req->dst0.CbrMst+req->dst0.w*2;
			break;

		case IPP_Y_CBCR_H2V1:
			dst0_YrgbMst =	req->dst0.YrgbMst+req->dst0.w;
			dst0_CbrMst  =	req->dst0.CbrMst+req->dst0.w;
			break;

		case IPP_Y_CBCR_H2V2:
			dst0_YrgbMst =	req->dst0.YrgbMst+req->dst0.w;
			dst0_CbrMst  =	req->dst0.CbrMst+req->dst0.w;
			break;

		default:
			break;
		}

	break;

	case IPP_ROT_Y_FLIP:
		DBG("rotate %d, src0.fmt %d",rotate,req->src0.fmt);
		switch(req->src0.fmt)
		{
		case IPP_XRGB_8888:
			dst0_YrgbMst =	req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w*4;
			dst0_CbrMst  = req->dst0.CbrMst;
			break;

		case IPP_RGB_565:
			dst0_YrgbMst =	req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w*2;
			dst0_CbrMst  = req->dst0.CbrMst;
			break;

		case IPP_Y_CBCR_H1V1:
			dst0_YrgbMst =	req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w;
			dst0_CbrMst = req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w*2;
			break;

		case IPP_Y_CBCR_H2V1:
			dst0_YrgbMst =	req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w;
			dst0_CbrMst = req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w;
			break;

		case IPP_Y_CBCR_H2V2:
			dst0_YrgbMst =	req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w;
			dst0_CbrMst = req->dst0.CbrMst+((req->dst0.h/2)-1)*req->dst_vir_w;
			break;

	default:
		break;
	}

	break;
	case IPP_ROT_0:
		//for  0 degree
		DBG("rotate %d, src0.fmt %d",rotate,req->src0.fmt);
		dst0_YrgbMst =	req->dst0.YrgbMst;
		dst0_CbrMst  = req->dst0.CbrMst;
	break;

	default:
		ERR("ipp is not surpport degree!!\n" );
		break;
	}
	
	//we start to interact with hw now
	wq_condition = 0;

	ipp_power_on();
	
	
	//check if IPP is idle
	if(((ipp_read(IPP_INT)>>6)&0x3) !=0)// idle
	{
		printk("IPP staus is not idle,can not set register\n");
		goto error_status;
	}


	/* Configure source image */
	DBG("src YrgbMst 0x%x , CbrMst0x%x,  %dx%d, fmt = %d\n", req->src0.YrgbMst,req->src0.CbrMst,
					req->src0.w, req->src0.h, req->src0.fmt);

	ipp_write(req->src0.YrgbMst, IPP_SRC0_Y_MST);
	if(IS_YCRCB(req->src0.fmt))
	{
		ipp_write(req->src0.CbrMst, IPP_SRC0_CBR_MST);
	}
	//ipp_write(req->src0.h<<16|req->src0.w, IPP_SRC_IMG_INFO);
	ipp_write((ipp_read(IPP_CONFIG)&(~0x7))|req->src0.fmt, IPP_CONFIG);

	/* Configure destination image */
	DBG("dst YrgbMst 0x%x , CbrMst0x%x, %dx%d\n", dst0_YrgbMst,dst0_CbrMst,
					req->dst0.w, req->dst0.h);

	ipp_write(dst0_YrgbMst, IPP_DST0_Y_MST);

	if(IS_YCRCB(req->src0.fmt))
	{
		ipp_write(dst0_CbrMst, IPP_DST0_CBR_MST);
	}

	ipp_write(req->dst0.h<<16|req->dst0.w, IPP_DST_IMG_INFO);

	/*Configure Pre_scale*/
	if((IPP_ROT_90 == rotate) || (IPP_ROT_270 == rotate))
	{
		pre_scale = ((req->dst0.w <= req->src0.h/2) ? 1 : 0)||((req->dst0.h <= req->src0.w/2) ? 1 : 0);
	}
	else //other degree
	{
		pre_scale = ((req->dst0.w <= req->src0.w/2) ? 1 : 0)||((req->dst0.h <= req->src0.h/2) ? 1 : 0);
	}

	if(pre_scale)
	{
		if(((IPP_ROT_90 == rotate) || (IPP_ROT_270 == rotate)))
		{
			if((req->src0.w>req->dst0.h))
			{
				pre_scale_w = (uint32_t)( req->src0.w/req->dst0.h);//floor
			}
			else
			{
			   pre_scale_w = 1;
			}
			if((req->src0.h>req->dst0.w))
			{
				pre_scale_h = (uint32_t)( req->src0.h/req->dst0.w);//floor
			}
			else
			{
				pre_scale_h = 1;
			}

			DBG("!!!!!pre_scale_h %d,pre_scale_w %d \n",pre_scale_h,pre_scale_w);
		}
		else//0 180 x ,y
		{
			if((req->src0.w>req->dst0.w))
			{
				pre_scale_w = (uint32_t)( req->src0.w/req->dst0.w);//floor
			}
			else
			{
			   pre_scale_w = 1;
			}

			if((req->src0.h>req->dst0.h))
			{
				pre_scale_h = (uint32_t)( req->src0.h/req->dst0.h);//floor
			}
			else
			{
				pre_scale_h = 1;
			}
			DBG("!!!!!pre_scale_h %d,pre_scale_w %d \n",pre_scale_h,pre_scale_w);
		}

		//pre_scale only support 1/2 to 1/8 time
		if(pre_scale_w > 8)
		{
			if(pre_scale_w < 16)
			{
				pre_scale_w = 8;
			}
			else
			{
				printk("invalid pre_scale operation! Down scaling ratio should not be more than 16!\n");
				goto error_scale;
			}
		}
		if(pre_scale_h > 8)
		{
			if(pre_scale_h < 16)
			{
				pre_scale_h = 8;
			}
			else
			{
				printk("invalid pre_scale operation! Down scaling ratio should not be more than 16!\n");
				goto error_scale;
			}
		}
			
		if((req->src0.w%pre_scale_w)!=0) //ceil
		{
			pre_scale_output_w = req->src0.w/pre_scale_w+1;
		}
		else
		{
			pre_scale_output_w = req->src0.w/pre_scale_w;
		}

		if((req->src0.h%pre_scale_h)!=0)//ceil
		{
			pre_scale_output_h	= req->src0.h/pre_scale_h +1;
		}
		else
		{
			pre_scale_output_h = req->src0.h/pre_scale_h;
		}

		//when fmt is YUV,make sure pre_scale_output_w and pre_scale_output_h are even
		if(IS_YCRCB(req->src0.fmt))
		{
			if((pre_scale_output_w & 0x1) != 0)
			{
				pre_scale_output_w -=1;
				src0_w = pre_scale_output_w * pre_scale_w;
			}
			if((pre_scale_output_h & 0x1) != 0)
			{
				pre_scale_output_h -=1;
				src0_h = pre_scale_output_h * pre_scale_h;
			}
		}
			
		ipp_write((ipp_read(IPP_CONFIG)&0xffffffef)|PRE_SCALE, IPP_CONFIG); 		//enable pre_scale
		ipp_write((pre_scale_h-1)<<3|(pre_scale_w-1),IPP_PRE_SCL_PARA);
		ipp_write(((pre_scale_output_h)<<16)|(pre_scale_output_w), IPP_PRE_IMG_INFO);

	}
	else//no pre_scale
	{
		ipp_write(ipp_read(IPP_CONFIG)&(~PRE_SCALE), IPP_CONFIG); //disable pre_scale
		ipp_write(0,IPP_PRE_SCL_PARA);
		ipp_write((req->src0.h<<16)|req->src0.w, IPP_PRE_IMG_INFO);
	}

	ipp_write(src0_h<<16|src0_w, IPP_SRC_IMG_INFO);
	
	/*Configure Post_scale*/
	if((IPP_ROT_90 == rotate) || (IPP_ROT_270 == rotate))
	{
		if (( (req->src0.h%req->dst0.w)!=0)||( (req->src0.w%req->dst0.h)!= 0)//non-interger down-scaling 
			||((req->src0.h/req->dst0.w)>8)||((req->src0.h/req->dst0.w)>8)	 //down-scaling ratio > 8
			||(req->dst0.w > req->src0.h)  ||(req->dst0.h > req->src0.w))	 //up-scaling
							
		{
			post_scale = 1;
		}
		else
		{
			post_scale = 0;
		}
	}
	else  //0 180 x-flip y-flip
	{
		if (( (req->src0.w%req->dst0.w)!=0)||( (req->src0.h%req->dst0.h)!= 0)//non-interger down-scaling 
			||((req->src0.w/req->dst0.w)>8)||((req->src0.h/req->dst0.h)>8)	 //down-scaling ratio > 8
			||(req->dst0.w > req->src0.w)  ||(req->dst0.h > req->src0.h))	 //up-scaling
		{
			post_scale = 1;
		}
		else
		{
			post_scale = 0;
		}
	}

	if(post_scale)
	{
		if(pre_scale)
		{
			post_scale_input_w = pre_scale_output_w;
			post_scale_input_h = pre_scale_output_h;
		}
		else
		{
			post_scale_input_w = req->src0.w;
			post_scale_input_h = req->src0.h;
		}
			
		if((IPP_ROT_90 == rotate) || (IPP_ROT_270 == rotate))
		{
			DBG("post_scale_input_w %d ,post_scale_input_h %d !!!\n",post_scale_input_w,post_scale_input_h);

			switch(req->src0.fmt)
			{
			case IPP_XRGB_8888:
			case IPP_RGB_565:
			case IPP_Y_CBCR_H1V1:
				//In horiaontial scale case, the factor must be minus 1 if the result of the factor is integer
				 if(((4096*(post_scale_input_w-1))%(req->dst0.h-1))==0)
				 {
					post_scale_w = (uint32_t)(4096*(post_scale_input_w-1)/(req->dst0.h-1))-1;
				 }
				 else
				 {
					 post_scale_w = (uint32_t)(4096*(post_scale_input_w-1)/(req->dst0.h-1));
				 }
				 break;

			case IPP_Y_CBCR_H2V1:
			case IPP_Y_CBCR_H2V2:
				//In horiaontial scale case, the factor must be minus 1 if the result of the factor is integer
				 if(((4096*(post_scale_input_w/2-1))%(req->dst0.h/2-1))==0)
				 {
					post_scale_w = (uint32_t)(4096*(post_scale_input_w/2-1)/(req->dst0.h/2-1))-1;
				 }
				 else
				 {
					 post_scale_w = (uint32_t)(4096*(post_scale_input_w/2-1)/(req->dst0.h/2-1));
				 }
				 break;

			default:
				break;
			}
			post_scale_h = (uint32_t)(4096*(post_scale_input_h -1)/(req->dst0.w-1));

			DBG("1111 post_scale_w %x,post_scale_h %x!!! \n",post_scale_w,post_scale_h);
		}
		else// 0 180 x-flip y-flip
		{
			switch(req->src0.fmt)
			{
			case IPP_XRGB_8888:
			case IPP_RGB_565:
			case IPP_Y_CBCR_H1V1:
				//In horiaontial scale case, the factor must be minus 1 if the result of the factor is integer
				 if(((4096*(post_scale_input_w-1))%(req->dst0.w-1))==0)
				 {
					post_scale_w = (uint32_t)(4096*(post_scale_input_w-1)/(req->dst0.w-1))-1;
				 }
				 else
				 {
					 post_scale_w = (uint32_t)(4096*(post_scale_input_w-1)/(req->dst0.w-1));
				 }
				 break;

			case IPP_Y_CBCR_H2V1:
			case IPP_Y_CBCR_H2V2:
				////In horiaontial scale case, the factor must be minus 1 if the result of the factor is integer
				 if(((4096*(post_scale_input_w/2-1))%(req->dst0.w/2-1))==0)
				 {
					post_scale_w = (uint32_t)(4096*(post_scale_input_w/2-1)/(req->dst0.w/2-1))-1;
				 }
				 else
				 {
					 post_scale_w = (uint32_t)(4096*(post_scale_input_w/2-1)/(req->dst0.w/2-1));
				 }
				 break;

			default:
				break;
			}
			post_scale_h = (uint32_t)(4096*(post_scale_input_h -1)/(req->dst0.h-1));

		}

		/*only support 1/2 to 4 times scaling,but two cases can pass
		1.176*144->480*800, YUV420 
		2.128*128->480*800, YUV420
		*/
		if(!((req->src0.fmt == IPP_Y_CBCR_H2V2)&&
			(((req->src0.w == 176)&&(req->src0.h == 144))||((req->src0.w == 128)&&(req->src0.h == 128)))&&
			((req->dst0.w == 480)&&(req->dst0.h == 800))))	
		{	
			
			if(post_scale_w<0x3ff || post_scale_w>0x1fff || post_scale_h<0x400 || post_scale_h>0x2000 )
			{
				printk("invalid post_scale para!\n");
				goto error_scale;
			}
		}
		ipp_write((ipp_read(IPP_CONFIG)&0xfffffff7)|POST_SCALE, IPP_CONFIG); //enable post_scale
		ipp_write((post_scale_h<<16)|post_scale_w, IPP_POST_SCL_PARA);
	}
	else //no post_scale
	{
		DBG("no post_scale !!!!!! \n");
		ipp_write(ipp_read(IPP_CONFIG)&(~POST_SCALE), IPP_CONFIG); //disable post_scale
		ipp_write((post_scale_h<<16)|post_scale_w, IPP_POST_SCL_PARA);
	}

	/* Configure rotation */

	if(IPP_ROT_0 == req->flag)
	{
		ipp_write(ipp_read(IPP_CONFIG)&(~ROT_ENABLE), IPP_CONFIG);
	}
	else
	{
		ipp_write(ipp_read(IPP_CONFIG)|ROT_ENABLE, IPP_CONFIG);
		ipp_write((ipp_read(IPP_CONFIG)&0xffffff1f)|(rotate<<5), IPP_CONFIG);
	}

	/*Configure deinterlace*/
	if(req->deinterlace_enable == 1)
	{
		//only support YUV format
		if(IS_YCRCB(req->src0.fmt))
		{
			//If pre_scale is enable, Deinterlace is done by scale filter
			if(!pre_scale)
			{
				//check the deinterlace parameters
				if((req->deinterlace_para0 < 32) && (req->deinterlace_para1 < 32) && (req->deinterlace_para2 < 32) 
					&& ((req->deinterlace_para0 + req->deinterlace_para1 + req->deinterlace_para2) == 32))
				{
					deinterlace_config = (req->deinterlace_enable<<24) | (req->deinterlace_para0<<19) | (req->deinterlace_para1<<14) | (req->deinterlace_para2<<9);
					DBG("para0 %d, para1 %d, para2 %d,deinterlace_config  %x\n",req->deinterlace_para0,req->deinterlace_para1,req->deinterlace_para2,deinterlace_config);
					#ifdef CONFIG_DEINTERLACE
						ipp_write((ipp_read(IPP_CONFIG)&0xFE0001FF)|deinterlace_config, IPP_CONFIG);
					#else
						printk("does not support deinterlacing!\n");
						ipp_write(ipp_read(IPP_CONFIG)&(~DEINTERLACE_ENABLE), IPP_CONFIG); //disable deinterlace
					#endif
				}
				else
				{
					ERR("invalid deinterlace parameters!\n");
				}
			}
		}
		else
		{
			ERR("only support YUV format!\n");
		}
	}
	else
	{
		ipp_write(ipp_read(IPP_CONFIG)&(~DEINTERLACE_ENABLE), IPP_CONFIG); //disable deinterlace
	}

	/*Configure other*/
	ipp_write((req->dst_vir_w<<16)|req->src_vir_w, IPP_IMG_VIR);

	//store clip mode 
	if(req->store_clip_mode == 1)
	{
		ipp_write(ipp_read(IPP_CONFIG)|STORE_CLIP_MODE, IPP_CONFIG);
	}
	else
	{
		ipp_write(ipp_read(IPP_CONFIG)&(~STORE_CLIP_MODE), IPP_CONFIG);
	}


	/* Start the operation */
	ipp_write(8, IPP_INT);		

	ipp_write(1, IPP_PROCESS_ST);

	dsb();
	dmac_clean_range(drvdata->ipp_base,drvdata->ipp_base+0x54);
#ifdef IPP_TEST
	hw_start = ktime_get(); 
#endif	

    goto error_noerror;


error_status:
error_scale:
	ret = -EINVAL;
	ipp_soft_reset();
	ipp_power_off(NULL);
erorr_input:
error_noerror:
	drvdata->ipp_result = ret;
	//printk("ipp_blit done\n");
	return ret;
}
Exemple #5
0
int
main( int argc, char **argv ) {
   int num_polled = 1;
   struct pollfd *polls;
   struct sockaddr_in incoming;
   int i, n, pos, len;
   int new_fd;
   socklen_t addr_len;
   Connection *conn;
   IPP *response;

   signal( SIGUSR1, quit_handler );

   // Temp printer for now
   if( argc < 2 ) {
     fprintf(stderr, "Missing argument pointing to location of printer definition file.\n" );
     exit(1);
   }

   if(!init_printers( argv[1] )) {
     fprintf( stderr, "Unable to load printer definition file %s\n", argv[1] );
     exit(1);
   }

   new_fd = StartListening();

   polls = malloc( sizeof( struct pollfd )  * MAX_CLIENTS);
   polls[0].fd = new_fd;
   polls[0].events = POLLIN;

   for(;;) {
     // printf(".");
     for( conn = list_conn( NULL ), num_polled = 1; conn != NULL; conn = list_conn( conn ) ) {
       if( conn->state == CONN_BEGIN || conn->state == CONN_PRINTING_READ ) {
         polls[num_polled].fd = conn->fd;
         polls[num_polled++].events = POLLIN;
       } else if( conn->state == CONN_OUTPUT ) {
         polls[num_polled].fd = conn->fd;
         polls[num_polled++].events = POLLOUT;
       }
     }
     for( i = 0; i < array_len( printers ); i++ ) {
       printer = array_get( printers, i );
       if( printer->state == PRINTER_PRINTING_WRITE ) {
         polls[num_polled].fd = printer->fd;
         polls[num_polled++].events = POLLOUT;
       }
     }

     poll( polls, num_polled, -1 );
     // printf("o" );
     for( i = 0; i < num_polled; i++ ) {
       if( polls[i].revents & POLLIN ) {
         // Read
         if( i == 0 ) { // Special case..
           addr_len = sizeof( struct sockaddr_in );
           new_fd = accept( polls[i].fd, (struct sockaddr *)&(incoming), &addr_len );
           add_conn( new_fd );
         } else {
           if( ( conn = get_conn( polls[i].fd ) ) ) {
             process_conn( conn );
           }
         }
       } else if ( polls[i].revents & POLLNVAL ) {
         if( ( conn = get_conn( polls[i].fd ) ) )
           remove_conn( conn );
       } else if ( polls[i].revents & POLLOUT ) {
         if( ( conn = get_conn( polls[i].fd ) ) ) {
           if( ( n = write( conn->fd, conn->buffer+conn->buf_ptr, conn->used-conn->buf_ptr ) ) ) {
             conn->buf_ptr += n;
             if( conn->buf_ptr == conn->used ) {
               close( conn->fd );
               remove_conn( conn );
             }
           }
         } else {
           int e;

           for( e = 0; e < array_len( printers ); e++ ) {
             printer = array_get( printers, e );
             if( printer->fd == polls[i].fd ) { 
               if( ( n = write( printer->fd, printer->buffer+printer->buf_ptr, printer->used-printer->buf_ptr ) ) == 0 ) {
#if 0
                 // ERROR WRITING TO PRINTER
                 // Simple error support -- close printer fd
                 if( ( conn = get_conn( printer->jobs->job.fd ) ) ) {
                   fprintf( stderr, "Print job error.\n" );
                   response = ipp_new();
                   response->response = 0x0504;
                   response->version = 256; // IPP 1.0
                   response->request_id = conn->ipp->request_id;
                   ipp_add_tag( response, IPP_TAG_OPERATIONS, NULL, NULL, 0, 0 );
                   ipp_copy_tag( response, conn->ipp, IPP_TAG_OPERATIONS, "attributes-charset" );
                   ipp_copy_tag( response, conn->ipp, IPP_TAG_OPERATIONS, "attributes-natural-language" );
                   len = ipp_write( response, NULL, len );
                   pos = sprintf( conn->buffer, "HTTP/1.1 200 OK\r\nContent-Type: application/ipp\r\nContent-Length: %d\r\n\r\n", len );
                   ipp_write( response, conn->buffer+pos, len );
                   conn->used = len + pos;
                   conn->buf_ptr = 0;
                   conn->state = CONN_OUTPUT;
                   ipp_free( response );
                 }
                 fprintf( stderr, "Marking printer closed.\n" );
                 close(printer->fd );
                 printer->state = PRINTER_CLOSED;
#endif /* 0 */
               } else {
                 printer->buf_ptr += n;
                 if( printer->buf_ptr == printer->used ) {
                   printer->state = PRINTER_PRINTING_WAIT;
                   printer->buf_ptr = printer->used = 0;
                   if( ( conn = get_conn( printer->jobs->job.fd ) ) == NULL ) {
                     printf( "Bad printer state.\n" );
                   }
                   if( conn->ipp->data_left )
                     conn->state = CONN_PRINTING_READ;
                   else {
                     int pos, len, val;
                     struct _ipp_jobs *old_job;
                     IPP *response;
                     // Generate a done message
                     response = ipp_new();
                     response->response = 0x0000; // Success
                     response->request_id = conn->ipp->request_id;
                     response->version = 256;
                     ipp_add_tag( response, IPP_TAG_OPERATIONS, NULL, NULL, 0, 0 );
                     ipp_copy_tag( response, conn->ipp, IPP_TAG_OPERATIONS, "attributes-charset" );
                     ipp_copy_tag( response, conn->ipp, IPP_TAG_OPERATIONS, "attributes-natural-language" );
                     /* 2004/11/8 : Added to make XP printer utility report success status*/
                     ipp_add_tag( response, IPP_TAG_TEXT_WO_LANG, "status-message", "successful-ok", strlen( "successful-ok" ), 0 );
    				 ipp_add_tag( response, IPP_TAG_JOBS, NULL, NULL, 0, 0 );
    				 val = printer->jobs->job.id;
    				 ipp_add_tag( response, IPP_TAG_INTEGERS, "job-id", &val, 4, 0 );
    				 val = 9;
    				 ipp_add_tag( response, IPP_TAG_ENUM, "job-state", &val, 4, 0 ); /* 9 = COMPLETED */
                     // Done
                     len = ipp_write( response, NULL, len );
                     pos = sprintf( conn->buffer, "HTTP/1.1 200 OK\r\nContent-Type: application/ipp\r\nContent-Length: %d\r\n\r\n", len );
                     ipp_write( response, conn->buffer + pos, len );
                     conn->used = len + pos;
                     conn->buf_ptr = 0;
                     conn->state = CONN_OUTPUT;
                     /* 2004/11/8: added to free response */
          			 ipp_free( response );
                     // The JOB being is printed is ALWAYS the first one
                     old_job = printer->jobs;
                     printer->jobs = old_job->next;
                     free( old_job ); // Free the job

                     printf( "Going to next job...\n" );
                     if( printer->jobs ) {
                       if( ( conn = get_conn( printer->jobs->job.fd ) ) ) {
                         if( conn->buf_ptr < conn->used ) {
                           memcpy( printer->buffer, conn->buffer + conn->buf_ptr, conn->used - conn->buf_ptr );
                           printer->used = conn->used - conn->buf_ptr;
                           printer->buf_ptr = 0;
                           printer->state = PRINTER_PRINTING_WRITE;
                           conn->state = CONN_PRINTING_WAIT;
                           conn->ipp->data_left -= conn->used - conn->buf_ptr;
                         } else {
                           if( conn->ipp->data_left ) {
                             printer->state = PRINTER_PRINTING_WAIT;
                             conn->state = CONN_PRINTING_READ;
                           }
                         }
                       } else {
                         printf( "Unable to get connection for FD - %d.\n", printer->jobs->job.fd );
                       }
                     } else {
                        /* printer->state = PRINTER_OPEN; */
                     	/* 2004/11/5 : put back into closed state so that kernel can remove lp0 when printer unplugged */
  	  					close(printer->fd);
  	  					printer->fd = 0;
  	  					printer->state = PRINTER_CLOSED;
                     }
                   }
                 } 
               }
             }
           }
         }  
       }
     }
  }
}