static int initialize_capture(v4l2_std_id * cur_std)
{
	int ret;
	printf("initializing capture device\n");
	init_capture_device();
	printf("setting data format\n");
	ret = set_data_format(cur_std);
	if (ret) {
		printf("Error in setting capture format\n");
		return ret;
	}
	printf("initializing capture buffers\n");
	ret = init_capture_buffers();
	if (ret) {
		printf("Failed to initialize capture buffers\n");
		return ret;
	}
	printf("initializing display device\n");
	ret = start_streaming();
	if (ret) {
		printf("Failed to start capture streaming\n");
		return ret;
	}
	return 0;
}
int init_camera_capture(void)
{
	int capt_fd;
    int ret = 0;
    struct v4l2_capability cap;

    if ((capt_fd = open(CAPTURE_DEVICE, O_RDWR | O_NONBLOCK, 0)) <= -1) {

        perror("init_camera_capture:open::");
		return -1;
    }

    /*Is capture supported? */
    if (-1 == ioctl(capt_fd, VIDIOC_QUERYCAP, &cap)) {
        perror("init_camera_capture:ioctl:VIDIOC_QUERYCAP:");
		close(capt_fd);
		return -1;
    }

    if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
        printf("InitDevice:capture is not supported on:%s\n",
               CAPTURE_DEVICE);
		close(capt_fd);
		return -1;
    }

    /*is MMAP-IO supported? */
    if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
        printf
            ("InitDevice:IO method MMAP is not supported on:%s\n",
             CAPTURE_DEVICE);
		close(capt_fd);
		return -1;
    }

	printf("setting data format\n");
	if (set_data_format(capt_fd) < 0) {
		printf("SetDataFormat failed\n");
		close(capt_fd);
		return -1;
	}

	printf("initializing capture buffers\n");
	if (InitCaptureBuffers(capt_fd) < 0) {
		printf("InitCaptureBuffers failed\n");
		close(capt_fd);
		return -1;
	}
	ret = start_capture_streaming(capt_fd);
	if (ret) {
		printf("Failed to start capture streaming\n");
		return ret;
	}
	printf("Capture initialized\n");
	return capt_fd;
}
Esempio n. 3
0
static int s3c_pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	s3c_pp_instance_context_t *current_instance;
	s3c_pp_params_t *parg;

	unsigned int temp = 0;
    mutex_lock(h_mutex);

	current_instance	= (s3c_pp_instance_context_t *) file->private_data;
	parg	            = (s3c_pp_params_t *) arg;

	switch ( cmd )
    {
		case S3C_PP_SET_PARAMS:
            {
                s3c_pp_out_path_t temp_out_path; 
                unsigned int temp_src_width, temp_src_height, temp_dst_width, temp_dst_height;
                s3c_color_space_t temp_src_color_space, temp_dst_color_space;

                get_user(temp_out_path, &parg->out_path);

                if ( (-1 != s3c_pp_instance_info.fifo_mode_instance_no )
                     || ((s3c_pp_instance_info.dma_mode_instance_count) && (FIFO_FREERUN == temp_out_path)) )
                {
                    printk ( KERN_ERR "\n%s: S3C_PP_SET_PARAMS can't be executed.\n", __FUNCTION__ );
                    mutex_unlock(h_mutex);
    			    return -EINVAL; 
                }

    			get_user(temp_src_width,       &parg->src_width);
    			get_user(temp_src_height,      &parg->src_height);
    			get_user(temp_dst_width,       &parg->dst_width);
    			get_user(temp_dst_height,      &parg->dst_height);

                // S3C6410 support that the source image is up to 4096 x 4096
                //     and the destination image is up to 2048 x 2048.
    			if (    (temp_src_width > 4096) || (temp_src_height > 4096) 
                     || (temp_dst_width > 2048) || (temp_dst_height > 2048) )
    			{
    				printk(KERN_ERR "\n%s: Size is too big to be supported.\n", __FUNCTION__);
    				mutex_unlock(h_mutex);
    				return -EINVAL;
    			}
                
                get_user(temp_src_color_space, &parg->src_color_space);
                get_user(temp_dst_color_space, &parg->dst_color_space);

                if (    ( (temp_src_color_space == YC420) && (temp_src_width % 8) )
                     || ( (temp_src_color_space == RGB16) && (temp_src_width % 2) ) 
                     || ( (temp_out_path == DMA_ONESHOT) && (    ((temp_dst_color_space == YC420) && (temp_dst_width % 8))
                                                              || ((temp_dst_color_space == RGB16) && (temp_dst_width % 2)))) )
                {
    				printk(KERN_ERR "\n%s: YUV420 image width must be a multiple of 8.\n", __FUNCTION__);
                    printk(KERN_ERR "%s: RGB16 must be a multiple of 2.\n", __FUNCTION__);
    				mutex_unlock(h_mutex);
    				return -EINVAL;
                } 
                
                
    			get_user(current_instance->src_full_width,  &parg->src_full_width);
    			get_user(current_instance->src_full_height, &parg->src_full_height);
    			get_user(current_instance->src_start_x,     &parg->src_start_x);
    			get_user(current_instance->src_start_y,     &parg->src_start_y);
    			current_instance->src_width                 = temp_src_width;
    			current_instance->src_height                = temp_src_height;
                current_instance->src_color_space           = temp_src_color_space;

    			get_user(current_instance->dst_full_width,  &parg->dst_full_width);
                get_user(current_instance->dst_full_height, &parg->dst_full_height);
                get_user(current_instance->dst_start_x,     &parg->dst_start_x);
    			get_user(current_instance->dst_start_y,     &parg->dst_start_y);
    			current_instance->dst_width                 = temp_dst_width;
    			current_instance->dst_height                = temp_dst_height;
                current_instance->dst_color_space           = temp_dst_color_space;

                current_instance->out_path                  = temp_out_path;

                if ( DMA_ONESHOT == current_instance->out_path )
                {
                    s3c_pp_instance_info.instance_state[current_instance->instance_no] = PP_INSTANCE_INUSE_DMA_ONESHOT;
                    s3c_pp_instance_info.dma_mode_instance_count++;               
                }
                else
                {
                    get_user(current_instance->scan_mode, &parg->scan_mode);

                    current_instance->dst_color_space = RGB30;

                    s3c_pp_instance_info.instance_state[current_instance->instance_no] = PP_INSTANCE_INUSE_FIFO_FREERUN;
                    s3c_pp_instance_info.fifo_mode_instance_no = current_instance->instance_no;
                    s3c_pp_instance_info.wincon0_value_before_fifo_mode = __raw_readl ( S3C_WINCON0 );
                
                    //.[ REDUCE_VCLK_SYOP_TIME
                    if ( current_instance->src_height > current_instance->dst_height )
                    {
                        int i;

                        for ( i=2; (current_instance->src_height >= (i * current_instance->dst_height)) && (i<8); i++ )
                        {
                        }

                        current_instance->src_full_width  *= i;
                        current_instance->src_full_height /= i;
                        current_instance->src_height      /= i;
                    }
                    //.] REDUCE_VCLK_SYOP_TIME
                }

                current_instance->value_changed |= PP_VALUE_CHANGED_PARAMS;
            }
			break;

		case S3C_PP_START:
            dprintk ( "%s: S3C_PP_START last_instance=%d, curr_instance=%d\n", __FUNCTION__, 
                        s3c_pp_instance_info.last_running_instance_no, current_instance->instance_no );

            if ( PP_INSTANCE_READY == s3c_pp_instance_info.instance_state[current_instance->instance_no] )
            {
                printk ( KERN_ERR "%s: S3C_PP_START must be executed after running S3C_PP_SET_PARAMS.\n", __FUNCTION__ );
                mutex_unlock(h_mutex);
			    return -EINVAL;
            }

            if ( current_instance->instance_no != s3c_pp_instance_info.last_running_instance_no )
            {
                __raw_writel(0x0<<31, s3c_pp_base + S3C_VPP_POSTENVID);
            
                temp = S3C_MODE2_ADDR_CHANGE_DISABLE | S3C_MODE2_CHANGE_AT_FRAME_END | S3C_MODE2_SOFTWARE_TRIGGER;
                __raw_writel(temp, s3c_pp_base + S3C_VPP_MODE_2);
                   
                set_clock_src(HCLK);
            
                // setting the src/dst color space
                set_data_format(current_instance);
            
                // setting the src/dst size 
                set_scaler(current_instance);
            
                // setting the src/dst buffer address
                set_src_addr(current_instance);
                set_dest_addr(current_instance);

                current_instance->value_changed = PP_VALUE_CHANGED_NONE;

                s3c_pp_instance_info.last_running_instance_no = current_instance->instance_no;
                s3c_pp_instance_info.running_instance_no = current_instance->instance_no;

                if ( PP_INSTANCE_INUSE_DMA_ONESHOT == s3c_pp_instance_info.instance_state[current_instance->instance_no] )
                { // DMA OneShot Mode
                    dprintk ( "%s: DMA_ONESHOT mode\n", __FUNCTION__ );

                    post_int_enable(1);
                    pp_dma_mode_set_and_start();


                    if ( !(file->f_flags & O_NONBLOCK) )
                    {
                        if (interruptible_sleep_on_timeout(&waitq, 500) == 0) 
                        {
                            printk(KERN_ERR "\n%s: Waiting for interrupt is timeout\n", __FUNCTION__);
                        }
                    }
                }
                else
                { // FIFO freerun Mode
                    dprintk ( "%s: FIFO_freerun mode\n", __FUNCTION__ );
                    s3c_pp_instance_info.fifo_mode_instance_no = current_instance->instance_no;

                    post_int_enable(1);
                    pp_fifo_mode_set_and_start(current_instance); 
                }
            }
            else
            {
                if ( current_instance->value_changed != PP_VALUE_CHANGED_NONE )
                {
                    __raw_writel(0x0<<31, s3c_pp_base + S3C_VPP_POSTENVID);

                    if ( current_instance->value_changed & PP_VALUE_CHANGED_PARAMS )
                    {
                        set_data_format(current_instance);
                        set_scaler(current_instance);
                    }

                    if ( current_instance->value_changed & PP_VALUE_CHANGED_SRC_BUF_ADDR_PHY )
                    {
                        set_src_addr(current_instance);
                    }

                    if ( current_instance->value_changed & PP_VALUE_CHANGED_DST_BUF_ADDR_PHY )
                    {
                        set_dest_addr(current_instance);
                    }

                    current_instance->value_changed = PP_VALUE_CHANGED_NONE;
                }

                s3c_pp_instance_info.running_instance_no = current_instance->instance_no;

                post_int_enable(1);
                start_processing();

                if ( !(file->f_flags & O_NONBLOCK) )
                {
                    if (interruptible_sleep_on_timeout(&waitq, 500) == 0) 
                    {
                        printk(KERN_ERR "\n%s: Waiting for interrupt is timeout\n", __FUNCTION__);
                    }
                }
            }
			break;

		case S3C_PP_GET_SRC_BUF_SIZE:

            if ( PP_INSTANCE_READY == s3c_pp_instance_info.instance_state[current_instance->instance_no] )
            {
                dprintk ( "%s: S3C_PP_GET_SRC_BUF_SIZE must be executed after running S3C_PP_SET_PARAMS.\n", __FUNCTION__ );
                mutex_unlock(h_mutex);
			    return -EINVAL;
            }

            temp = cal_data_size ( current_instance->src_color_space, current_instance->src_full_width, current_instance->src_full_height );

			mutex_unlock(h_mutex);
			return temp;


		case S3C_PP_SET_SRC_BUF_ADDR_PHY:

            get_user(current_instance->src_buf_addr_phy, &parg->src_buf_addr_phy);
            current_instance->value_changed |= PP_VALUE_CHANGED_SRC_BUF_ADDR_PHY;
			break;

        case S3C_PP_SET_SRC_BUF_NEXT_ADDR_PHY:

            if ( current_instance->instance_no != s3c_pp_instance_info.fifo_mode_instance_no )
            { // if FIFO Mode is not Active
                dprintk (KERN_DEBUG "%s: S3C_PP_SET_SRC_BUF_NEXT_ADDR_PHY can't be executed.\n", __FUNCTION__ );
                mutex_unlock(h_mutex);
                return -EINVAL;
            }            

            get_user(current_instance->src_next_buf_addr_phy, &parg->src_next_buf_addr_phy);

            temp = __raw_readl(s3c_pp_base + S3C_VPP_MODE_2);
            temp |= (0x1<<4);
            __raw_writel(temp, s3c_pp_base + S3C_VPP_MODE_2);
    
            set_src_next_buf_addr(current_instance);

            temp = __raw_readl(s3c_pp_base + S3C_VPP_MODE_2);
            temp &= ~(0x1<<4);
            __raw_writel(temp, s3c_pp_base + S3C_VPP_MODE_2);
            break;

		case S3C_PP_GET_DST_BUF_SIZE:
            
            if ( PP_INSTANCE_READY == s3c_pp_instance_info.instance_state[current_instance->instance_no] )
            {
                dprintk ( "%s: S3C_PP_GET_DST_BUF_SIZE must be executed after running S3C_PP_SET_PARAMS.\n", __FUNCTION__ );
                mutex_unlock(h_mutex);
			    return -EINVAL;
            }

            temp = cal_data_size ( current_instance->dst_color_space, current_instance->dst_full_width, current_instance->dst_full_height );

			mutex_unlock(h_mutex);
			return temp;

		case S3C_PP_SET_DST_BUF_ADDR_PHY:

            get_user(current_instance->dst_buf_addr_phy, &parg->dst_buf_addr_phy);
            current_instance->value_changed |= PP_VALUE_CHANGED_DST_BUF_ADDR_PHY;
			break;


        case S3C_PP_ALLOC_KMEM:
            {
                s3c_pp_mem_alloc_t param;
                
                if (copy_from_user(&param, (s3c_pp_mem_alloc_t *)arg, sizeof(s3c_pp_mem_alloc_t)))
                {
                    mutex_unlock(h_mutex);
                    return -EFAULT;
                }
                
                flag = ALLOC_KMEM;
                
                param.vir_addr = do_mmap(file, 0, param.size, PROT_READ|PROT_WRITE, MAP_SHARED, 0);
                dprintk (KERN_DEBUG "param.vir_addr = %08x\n", param.vir_addr);
                            
                flag = 0;

                if(param.vir_addr == -EINVAL) {
                    printk(KERN_ERR "%s: PP_MEM_ALLOC FAILED\n", __FUNCTION__);
                    mutex_unlock(h_mutex);
                    return -EFAULT;
                }
                param.phy_addr = physical_address;
                
                dprintk (KERN_DEBUG "KERNEL MALLOC : param.phy_addr = 0x%X \t size = %d \t param.vir_addr = 0x%X\n", param.phy_addr, param.size, param.vir_addr);
                
                if (copy_to_user((s3c_pp_mem_alloc_t *)arg, &param, sizeof(s3c_pp_mem_alloc_t)))
                {
                    mutex_unlock(h_mutex);
                    return -EFAULT;
                }
            }
            break;

        case S3C_PP_FREE_KMEM:
            {
                s3c_pp_mem_alloc_t param;
                struct mm_struct *mm = current->mm;
                void *virt_addr;

                if ( copy_from_user(&param, (s3c_pp_mem_alloc_t *)arg, sizeof(s3c_pp_mem_alloc_t)) )
                {
                    mutex_unlock(h_mutex);
                    return -EFAULT;
                }
            
                dprintk (KERN_DEBUG "KERNEL FREE : param.phy_addr = 0x%X \t size = %d \t param.vir_addr = 0x%X\n", param.phy_addr, param.size, param.vir_addr);
            
                if ( do_munmap(mm, param.vir_addr, param.size ) < 0 ) 
                {
                    dprintk("do_munmap() failed !!\n");
                    mutex_unlock(h_mutex);
                    return -EINVAL;
                }
                virt_addr = phys_to_virt(param.phy_addr);
                dprintk ( "KERNEL : virt_addr = 0x%X\n", (unsigned int) virt_addr );
            
                kfree(virt_addr);
                param.size = 0;

                dprintk(KERN_DEBUG "do_munmap() succeed !!\n");
            }
            break;

        case S3C_PP_GET_RESERVED_MEM_SIZE:
            mutex_unlock(h_mutex);
            return PP_RESERVED_MEM_SIZE;

        case S3C_PP_GET_RESERVED_MEM_ADDR_PHY:
            mutex_unlock(h_mutex);
            return PP_RESERVED_MEM_ADDR_PHY;

		default:
			mutex_unlock(h_mutex);
			return -EINVAL;
	}

	mutex_unlock(h_mutex);
	
	return 0;
}
Esempio n. 4
0
/* init framebuffer*/
static PSD
fb_open(PSD psd)
{
	PSUBDRIVER subdriver;
	char *env;

	/* set statically in struct definition, may be overridden before calling fb_open*/
	//psd->xres = psd->xvirtres = SCREEN_WIDTH;
	//psd->yres = psd->yvirtres = SCREEN_HEIGHT;

	/* use pixel format to set bpp*/
	psd->pixtype = MWPIXEL_FORMAT;
	switch (psd->pixtype) {
	case MWPF_TRUECOLORARGB:
	case MWPF_TRUECOLORABGR:
	default:
		psd->bpp = 32;
		break;

	case MWPF_TRUECOLORRGB:
		psd->bpp = 24;
		break;

	case MWPF_TRUECOLOR565:
	case MWPF_TRUECOLOR555:
		psd->bpp = 16;
		break;

	case MWPF_TRUECOLOR332:
		psd->bpp = 8;
		break;

#if MWPIXEL_FORMAT == MWPF_PALETTE
	case MWPF_PALETTE:
		psd->bpp = SCREEN_DEPTH;
		break;
#endif
	}
	psd->planes = 1;

	/* set standard data format from bpp and pixtype*/
	psd->data_format = set_data_format(psd);

	/* Calculate the correct size and pitch from xres, yres and bpp*/
	GdCalcMemGCAlloc(psd, psd->xres, psd->yres, psd->planes, psd->bpp, &psd->size, &psd->pitch);

	psd->ncolors = (psd->bpp >= 24)? (1 << 24): (1 << psd->bpp);
	psd->flags = PSF_SCREEN;
	psd->portrait = MWPORTRAIT_NONE;

	/* select an fb subdriver matching our planes and bpp for backing store*/
	subdriver = select_fb_subdriver(psd);
	psd->orgsubdriver = subdriver;
	if (!subdriver)
		return NULL;

	/* set subdriver into screen driver*/
	set_subdriver(psd, subdriver);

#ifdef PATH_FRAMEBUFFER
	/* try opening framebuffer file for mmap*/
	if((env = getenv("FRAMEBUFFER")) == NULL)
		env = PATH_FRAMEBUFFER;
	fb = open(env, O_RDWR);
#endif
	if (fb >= 0) {
		/* mmap framebuffer into this address space*/
		psd->size = (psd->size + getpagesize() - 1) / getpagesize() * getpagesize();
		psd->addr = mmap(NULL, psd->size, PROT_READ|PROT_WRITE, MAP_SHARED, fb, 0);
		if (psd->addr == NULL || psd->addr == (unsigned char *)-1) {
			EPRINTF("Error mmaping shared framebuffer %s: %m\n", env);
			close(fb);
			return NULL;
		}
	} else {
		/* allocate framebuffer*/
		if ((psd->addr = malloc(psd->size)) == NULL)
			return NULL;
		psd->flags |= PSF_ADDRMALLOC;
	}

	/* allocate update region*/
	fb_updateregion = GdAllocRegion();

	return psd;	/* success*/
}
Esempio n. 5
0
/* init framebuffer*/
static PSD
fb_open(PSD psd)
{
    PSUBDRIVER subdriver;
    struct lcd_info li;

    assert(status < 2);

    // Initialize LCD screen
    lcd_init(16);
    lcd_getinfo(&li);

	psd->portrait = MWPORTRAIT_NONE;
    psd->xres = psd->xvirtres = li.width;
    psd->yres = psd->yvirtres = li.height;
    psd->planes = 1;
    psd->bpp = li.bpp;
    psd->ncolors = (psd->bpp >= 24)? (1 << 24): (1 << psd->bpp);
	psd->pitch = li.rlen;
	psd->size = psd->yres * psd->pitch;
    psd->flags = PSF_SCREEN;

    /* set pixel format*/
    switch (li.type) {
    case FB_TRUE_RGB565:
        psd->pixtype = MWPF_TRUECOLOR565;
        break;
    default:
        EPRINTF("Unsupported display type: %d\n", li.type);
        goto fail;
    }
#if 0
    if(1 /*visual == FB_VISUAL_TRUECOLOR || visual == FB_VISUAL_DIRECTCOLOR*/) {
        switch(psd->bpp) {
        case 8:
            psd->pixtype = MWPF_TRUECOLOR332;
            break;
        case 16:
            psd->pixtype = MWPF_TRUECOLOR565;
            break;
        case 24:
            psd->pixtype = MWPF_TRUECOLOR888;
            break;
        case 32:
            psd->pixtype = MWPF_TRUECOLOR8888;
            break;
        default:
            EPRINTF("Unsupported %d color (%d bpp) truecolor framebuffer\n", psd->ncolors, psd->bpp);
            goto fail;
        }
    } else psd->pixtype = MWPF_PALETTE;
#endif

    diag_printf("%dx%dx%d pitch %d type %d bpp %d\n", psd->xres,
      psd->yres, psd->ncolors, psd->pitch, li.type, psd->bpp);

	/* set standard data format from bpp and pixtype*/
	psd->data_format = set_data_format(psd);

    /* select a framebuffer subdriver based on planes and bpp*/
    subdriver = select_fb_subdriver(psd);
    if (!subdriver) {
        EPRINTF("No driver for screen bpp %d\n", psd->bpp);
        goto fail;
    }

	/* set subdriver into screen driver */
	set_subdriver(psd, subdriver);

    /* mmap framebuffer into this address space*/
    psd->addr = li.fb;
    if(psd->addr == NULL || psd->addr == (unsigned char *)-1) {
//        EPRINTF("Error mmaping %s: %m\n", env);
        goto fail;
    }

#if 0    /* FIXME */
    /* save original palette*/
    ioctl_getpalette(0, 16, saved_red, saved_green, saved_blue);

    /* setup direct color palette if required (ATI cards)*/
    if(visual == FB_VISUAL_DIRECTCOLOR)
        set_directcolor_palette(psd);
#endif

    status = 2;
    return psd;	/* success*/

 fail:
    return NULL;
}
Esempio n. 6
0
/*
**	Open graphics
*/
static PSD
DJGR_open(PSD psd)
{
	PSUBDRIVER subdriver;

	GrVideoMode	*md_info;
	
	int vwidth,vheight,vbpp;
	
	vwidth = SCREEN_WIDTH;
	vheight = SCREEN_HEIGHT;
	if(SCREEN_PIXTYPE == MWPF_TRUECOLOR8888) {
		vbpp=32;
	} else if(SCREEN_PIXTYPE == MWPF_TRUECOLOR888) {
		vbpp=24;
	} else if(SCREEN_PIXTYPE == MWPF_TRUECOLOR565)  {
		vbpp=16;
	} else {
		vbpp=8; //palette
	}

    GrSetMode(GR_width_height_bpp_graphics,vwidth,vheight,vbpp);

    md_info = (GrVideoMode *) GrCurrentVideoMode();

	psd->xres = psd->xvirtres = GrScreenX();
	psd->yres = psd->yvirtres = GrScreenY();
	psd->planes = 1;
	psd->bpp = md_info->bpp;
	psd->ncolors = psd->bpp >= 24 ? (1 << 24) : (1 << psd->bpp);
	psd->flags = PSF_SCREEN | PSF_ADDRMALLOC;
	/* Calculate the correct size and linelen here */
	GdCalcMemGCAlloc(psd, psd->xres, psd->yres, psd->planes, psd->bpp,
		&psd->size, &psd->pitch);

    if(psd->bpp == 32) {
		psd->pixtype = MWPF_TRUECOLOR8888;	
	} else if(psd->bpp == 16) {
		psd->pixtype = MWPF_TRUECOLOR565; 
	} else if(psd->bpp == 24)  {
		psd->pixtype = MWPF_TRUECOLOR888;
	} else {
		psd->pixtype = MWPF_PALETTE;
	}
		  
  psd->portrait = MWPORTRAIT_NONE;
  psd->data_format = set_data_format(psd);

  /*
   * set and initialize subdriver into screen driver
   * psd->size is calculated by subdriver init
   */
  subdriver = select_fb_subdriver(psd);
  
  psd->orgsubdriver = subdriver;

  set_subdriver(psd, subdriver);

  if ((psd->addr = malloc(psd->size)) == NULL)
		return NULL;

  return psd;

}
Esempio n. 7
0
static PSD
n3ds888_open(PSD psd)
{
  PSUBDRIVER subdriver;

  /* init driver variables depending on ega/vga mode*/
  psd->xres = psd->xvirtres = 240;
  psd->yres = psd->yvirtres = 340;
  psd->planes = 1;
  psd->bpp = 24;
  psd->ncolors = psd->bpp >= 24? (1 << 24): (1 << psd->bpp);
  psd->pixtype = MWPF_TRUECOLOR888;
  psd->portrait = MWPORTRAIT_NONE;
  psd->data_format = set_data_format(psd);

  /* Calculate the correct size and pitch from xres, yres and bpp*/
  GdCalcMemGCAlloc(psd, psd->xres, psd->yres, psd->planes, psd->bpp,
		   &psd->size, &psd->pitch);

  psd->flags = PSF_SCREEN;

  /*
   * set and initialize subdriver into screen driver
   * psd->size is calculated by subdriver init
   */
  
  // Currently attempting to use FB16 subdriver
  subdriver = select_fb_subdriver(psd);

  // Check that a valid subdriver exists
  if (!subdriver) 
    {
      EPRINTF("No driver for screen bpp %d\n", psd->bpp);
      return NULL;
    }
 
  psd->orgsubdriver = subdriver;

  set_subdriver(psd, subdriver);

//FB_BOT_1
//  psd->addr = (void*) 0x0008CA00//launcher 0x202118E0;

	srvInit();			// mandatory
	aptInit();			// mandatory
	hidInit(NULL);	// input (buttons, screen)

  gfxInit();
//  screenBottom=0x48F000;
//  screenBottom=gfxGetFramebuffer(GFX_BOTTOM, GFX_BOTTOM, NULL, NULL);

  psd->addr = (void*) gfxGetFramebuffer(GFX_BOTTOM, GFX_BOTTOM, NULL, NULL);
  printf('nano-x --> n3ds888_open \n');
  gfxFlushBuffers();


//    0x1E6000-0x22C500 -- top screen 3D left framebuffer 0(240x400x3) (The "3D right first-framebuf" addr stored in the LCD register is set to this, when the 3D is set to "off")
//    0x22C800-0x272D00 -- top screen 3D left framebuffer 1(240x400x3)
//    0x273000-0x2B9500 -- top screen 3D right framebuffer 0(240x400x3)
//    0x2B9800-0x2FFD00 -- top screen 3D right framebuffer 1(240x400x3)
//    0x48F000-0x4C7400 -- bottom screen framebuffer 0(240x320x3)
//    0x4C7800-0x4FF800 -- bottom screen framebuffer 1(240x320x3) 

  return psd;
}