static void gfb_free_framebuffer_work(struct work_struct *work) { struct gfb_data *data = container_of(work, struct gfb_data, free_framebuffer_work.work); struct fb_info *info = data->fb_info; /* int node = info->node; */ unregister_framebuffer(info); if (info->cmap.len != 0) fb_dealloc_cmap(&info->cmap); if (info->monspecs.modedb) fb_destroy_modedb(info->monspecs.modedb); if (info->screen_base) vfree(info->screen_base); fb_destroy_modelist(&info->modelist); fb_deferred_io_cleanup(info); usb_free_urb(data->fb_urb); vfree(data->fb_bitmap); kfree(data->fb_vbitmap); framebuffer_release(info); kfree(data); }
static int __devexit rk616_hdmi_remove(struct platform_device *pdev) { if(hdmi) { mutex_lock(&hdmi->enable_mutex); if(!hdmi->suspend && hdmi->enable && hdmi->irq) disable_irq(hdmi->irq); mutex_unlock(&hdmi->enable_mutex); if (hdmi->irq) { free_irq(hdmi->irq, NULL); } flush_workqueue(hdmi->workqueue); destroy_workqueue(hdmi->workqueue); #ifdef CONFIG_SWITCH switch_dev_unregister(&(hdmi->switch_hdmi)); #endif hdmi_unregister_display_sysfs(hdmi); #ifdef CONFIG_HAS_EARLYSUSPEND unregister_early_suspend(&hdmi->early_suspend); #endif fb_destroy_modelist(&hdmi->edid.modelist); if(hdmi->edid.audio) kfree(hdmi->edid.audio); if(hdmi->edid.specs) { if(hdmi->edid.specs->modedb) kfree(hdmi->edid.specs->modedb); kfree(hdmi->edid.specs); } kfree(hdmi); hdmi = NULL; } hdmi_dbg(hdmi->dev, "rk616 hdmi removed.\n"); return 0; }
static void vga_set_modelist(void) { int i, j = 0, modelen = 0; struct fb_videomode *mode = NULL; struct list_head *modelist = &ddev->modelist; struct fb_monspecs *specs = &ddev->specs; int pixclock; fb_destroy_modelist(modelist); for(i = 1; i <= specs->modedb_len; i++) { mode = &specs->modedb[i % specs->modedb_len]; //printk("%d %d %d %d %d %d %d %d %d %d %d %d %d\n",mode->refresh,mode->xres,mode->yres,mode->pixclock,mode->left_margin,mode->right_margin,mode->upper_margin, \ // mode->lower_margin,mode->hsync_len,mode->vsync_len, mode->sync,mode->vmode,mode->flag); pixclock = PICOS2KHZ(mode->pixclock); if (pixclock < (specs->dclkmax / 1000)) { for (j = 0; j < get_vga_mode_len(); j++) { if (default_modedb[j].xres == mode->xres && default_modedb[j].yres == mode->yres && (default_modedb[j].refresh == mode->refresh || default_modedb[j].refresh == mode->refresh + 1 || default_modedb[j].refresh == mode->refresh -1 )) { fb_add_videomode(&default_modedb[j], modelist); modelen++; break; } } } } ddev->modelen = modelen; }
static int __devexit cat66121_hdmi_i2c_remove(struct i2c_client *client) { hdmi_dbg(hdmi->dev, "%s\n", __func__); if(hdmi) { mutex_lock(&hdmi->enable_mutex); if(!hdmi->suspend && hdmi->enable && hdmi->irq) disable_irq(hdmi->irq); mutex_unlock(&hdmi->enable_mutex); if(hdmi->irq) free_irq(hdmi->irq, NULL); flush_workqueue(hdmi->workqueue); destroy_workqueue(hdmi->workqueue); #ifdef CONFIG_SWITCH switch_dev_unregister(&(hdmi->switch_hdmi)); #endif hdmi_unregister_display_sysfs(hdmi); #ifdef CONFIG_HAS_EARLYSUSPEND unregister_early_suspend(&hdmi->early_suspend); #endif fb_destroy_modelist(&hdmi->edid.modelist); if(hdmi->edid.audio) kfree(hdmi->edid.audio); if(hdmi->edid.specs) { if(hdmi->edid.specs->modedb) kfree(hdmi->edid.specs->modedb); kfree(hdmi->edid.specs); } kfree(hdmi); hdmi = NULL; } return 0; }
void hdmi_sys_remove(struct hdmi *hdmi) { int audio_need; audio_need = hdmi->edid.base_audio_support == 1 && hdmi->edid.sink_hdmi == 1; fb_destroy_modelist(&hdmi->edid.modelist); kfree(hdmi->edid.audio); if (hdmi->edid.specs) { kfree(hdmi->edid.specs->modedb); kfree(hdmi->edid.specs); } memset(&hdmi->edid, 0, sizeof(struct hdmi_edid)); INIT_LIST_HEAD(&hdmi->edid.modelist); hdmi->display = HDMI_DISABLE; if (hdmi->set_vif) hdmi->set_vif(hdmi, hdmi->lcdc->cur_screen, 0); rk_fb_switch_screen(hdmi->lcdc->cur_screen, 0, hdmi->lcdc->id); kobject_uevent_env(&hdmi->ddev->dev->kobj, KOBJ_REMOVE, envp); #ifdef CONFIG_SWITCH if (audio_need || rk_fb_get_display_policy() == DISPLAY_POLICY_BOX) switch_set_state(&(hdmi->switch_hdmi), 0); #endif rockchip_clear_system_status(SYS_STATUS_HDMI); }
void hdmi_sys_remove(void) { fb_destroy_modelist(&hdmi->edid.modelist); if(hdmi->edid.audio) kfree(hdmi->edid.audio); if(hdmi->edid.specs) { if(hdmi->edid.specs->modedb) kfree(hdmi->edid.specs->modedb); kfree(hdmi->edid.specs); } memset(&hdmi->edid, 0, sizeof(struct hdmi_edid)); INIT_LIST_HEAD(&hdmi->edid.modelist); hdmi->display = HDMI_DISABLE; if(hdmi->set_vif) hdmi->set_vif(hdmi->lcdc->screen1,0); rk_fb_switch_screen(hdmi->lcdc->screen1, 0, hdmi->lcdc->id); kobject_uevent_env(&hdmi->dev->kobj, KOBJ_REMOVE, envp); #ifdef CONFIG_SWITCH switch_set_state(&(hdmi->switch_hdmi), 0); #endif #ifdef CONFIG_RK_HDMI_CTL_CODEC codec_set_spk(1); fg_hdmi_open = 0; #endif }
static void adf_fbdev_fill_modelist(struct adf_fbdev *fbdev) { struct drm_mode_modeinfo *modelist; struct fb_videomode fbmode; size_t n_modes, i; int ret = 0; n_modes = adf_interface_modelist(fbdev->intf, NULL, 0); modelist = kzalloc(sizeof(modelist[0]) * n_modes, GFP_KERNEL); if (!modelist) { dev_warn(fbdev->info->dev, "allocating new modelist failed; keeping old modelist\n"); return; } adf_interface_modelist(fbdev->intf, modelist, n_modes); fb_destroy_modelist(&fbdev->info->modelist); for (i = 0; i < n_modes; i++) { adf_modeinfo_to_fb_videomode(&modelist[i], &fbmode); ret = fb_add_videomode(&fbmode, &fbdev->info->modelist); if (ret < 0) dev_warn(fbdev->info->dev, "adding mode %s to modelist failed: %d\n", modelist[i].name, ret); } kfree(modelist); }
static int hdmi_sys_parse_edid(struct hdmi* hdmi) { struct hdmi_edid *pedid; unsigned char *buff = NULL; int rc = HDMI_ERROR_SUCESS, extendblock = 0, i; if(hdmi == NULL) return HDMI_ERROR_FALSE; fb_destroy_modelist(&hdmi->edid.modelist); pedid = &(hdmi->edid); memset(pedid, 0, sizeof(struct hdmi_edid)); INIT_LIST_HEAD(&pedid->modelist); buff = kmalloc(EDID_BLOCK_LENGTH, GFP_KERNEL); if(buff == NULL) { hdmi_dbg(hdmi->dev, "[%s] can not allocate memory for edid buff.\n", __FUNCTION__); return -1; } // Read base block edid. memset(buff, 0 , EDID_BLOCK_LENGTH); rc = hdmi->ops->read_edid(hdmi, 0, buff); if(rc) { dev_err(hdmi->dev, "[HDMI] read edid base block error\n"); goto out; } rc = HDMI_EDID_parse_base(buff, &extendblock, pedid); if(rc) { dev_err(hdmi->dev, "[HDMI] parse edid base block error\n"); goto out; } for(i = 1; i < extendblock + 1; i++) { memset(buff, 0 , EDID_BLOCK_LENGTH); rc = hdmi->ops->read_edid(hdmi, i, buff); if(rc) { printk("[HDMI] read edid block %d error\n", i); goto out; } rc = HDMI_EDID_parse_extensions(buff, pedid); if(rc) { dev_err(hdmi->dev, "[HDMI] parse edid block %d error\n", i); continue; } } out: if(buff) kfree(buff); rc = ext_hdmi_ouputmode_select(hdmi, rc); return rc; }
static void vga_set_default_modelist(void) { int i, j = 0, modelen = 0; struct fb_videomode *mode = NULL; struct list_head *modelist = &ddev->modelist; struct fb_monspecs *specs = &ddev->specs; int pixclock; fb_destroy_modelist(modelist); modelen = get_vga_mode_len(); for(i = 0; i < modelen; i++) { fb_add_videomode(&default_modedb[i], modelist); } ddev->modelen = modelen; }
static void hdmi_sys_unplug(struct hdmi* hdmi) { if(hdmi->ops->remove) hdmi->ops->remove(hdmi); fb_destroy_modelist(&hdmi->edid.modelist); if(hdmi->edid.audio) kfree(hdmi->edid.audio); if(hdmi->edid.specs) { if(hdmi->edid.specs->modedb) kfree(hdmi->edid.specs->modedb); kfree(hdmi->edid.specs); } memset(&hdmi->edid, 0, sizeof(struct hdmi_edid)); ext_hdmi_init_modelist(hdmi); hdmi->hpd_status = HDMI_RECEIVER_REMOVE; // hdmi->config_set.display_on = HDMI_DISPLAY_OFF; // hdmi->auto_config = HDMI_AUTO_CONFIG; }
void hdmi_sys_remove(void) { int audio_need; audio_need = hdmi->edid.base_audio_support == 1 && hdmi->edid.sink_hdmi == 1; fb_destroy_modelist(&hdmi->edid.modelist); if(hdmi->edid.audio) kfree(hdmi->edid.audio); if(hdmi->edid.specs) { if(hdmi->edid.specs->modedb) kfree(hdmi->edid.specs->modedb); kfree(hdmi->edid.specs); } memset(&hdmi->edid, 0, sizeof(struct hdmi_edid)); INIT_LIST_HEAD(&hdmi->edid.modelist); hdmi->display = HDMI_DISABLE; if(hdmi->set_vif) hdmi->set_vif(hdmi->lcdc->screen1,0); rk_fb_switch_screen(hdmi->lcdc->screen1, 0, hdmi->lcdc->id); kobject_uevent_env(&hdmi->dev->kobj, KOBJ_REMOVE, envp); #ifdef CONFIG_SWITCH if(audio_need) switch_set_state(&(hdmi->switch_hdmi), 0); #endif #ifdef CONFIG_RK_HDMI_CTL_CODEC #ifdef CONFIG_MACH_RK_FAC #ifdef CONFIG_SND_RK29_SOC_ES8323 es8323_codec_set_spk(1); #endif #ifdef CONFIG_SND_RK29_SOC_RT5616 rt5616_codec_set_spk(1); #endif #ifdef CONFIG_SND_RK_SOC_RK616 rk616_codec_set_spk(1); #endif #else codec_set_spk(1); #endif #endif }
void hdmi_sys_remove(void) { fb_destroy_modelist(&hdmi->edid.modelist); if(hdmi->edid.audio) kfree(hdmi->edid.audio); if(hdmi->edid.specs) { if(hdmi->edid.specs->modedb) kfree(hdmi->edid.specs->modedb); kfree(hdmi->edid.specs); } memset(&hdmi->edid, 0, sizeof(struct hdmi_edid)); hdmi_init_modelist(hdmi); hdmi->display = HDMI_DISABLE; rk_fb_switch_screen(hdmi->lcdc->screen, 0, HDMI_SOURCE_DEFAULT); hdmi_sys_send_uevent(KOBJ_REMOVE); #ifdef CONFIG_SWITCH switch_set_state(&(hdmi->switch_hdmi), 0); #endif #ifdef CONFIG_HDMI_RK30_CTL_CODEC codec_set_spk(1); #endif }
static void det_worker(struct work_struct *work) { BYTE HPD, HPDChange ; char event_string[16]; char *envp[] = { event_string, NULL }; CheckHDMITX(&HPD, &HPDChange); if (HPDChange) { /* cable connection changes */ if (HPD) { ite661x.cable_plugin = 1; sprintf(event_string, "EVENT=plugin"); /* make sure fb is powerdown */ acquire_console_sem(); fb_blank(ite661x.fbi, FB_BLANK_POWERDOWN); release_console_sem(); if (ite661x_read_edid(ite661x.fbi) < 0) dev_err(&ite661x.client->dev, "ite661x: read edid fail\n"); else { ParseEDID(ite661x.edid + 128); if (ite661x.fbi->monspecs.modedb_len > 0) { int i; const struct fb_videomode *mode; struct fb_videomode m; fb_destroy_modelist(&ite661x.fbi->modelist); for (i = 0; i < ite661x.fbi->monspecs.modedb_len; i++) { /*FIXME now we do not support interlaced mode */ if (!(ite661x.fbi->monspecs.modedb[i].vmode & FB_VMODE_INTERLACED)) fb_add_videomode(&ite661x.fbi->monspecs.modedb[i], &ite661x.fbi->modelist); } fb_var_to_videomode(&m, &ite661x.fbi->var); mode = fb_find_nearest_mode(&m, &ite661x.fbi->modelist); fb_videomode_to_var(&ite661x.fbi->var, mode); ite661x.fbi->var.activate |= FB_ACTIVATE_FORCE; acquire_console_sem(); ite661x.fbi->flags |= FBINFO_MISC_USEREVENT; fb_set_var(ite661x.fbi, &ite661x.fbi->var); ite661x.fbi->flags &= ~FBINFO_MISC_USEREVENT; release_console_sem(); } acquire_console_sem(); fb_blank(ite661x.fbi, FB_BLANK_UNBLANK); release_console_sem(); HDMITX_SetOutput(); } } else { ite661x.cable_plugin = 0; sprintf(event_string, "EVENT=plugout"); acquire_console_sem(); fb_blank(ite661x.fbi, FB_BLANK_POWERDOWN); release_console_sem(); DisableAudioOutput(); DisableVideoOutput(); } kobject_uevent_env(&ite661x.pdev->dev.kobj, KOBJ_CHANGE, envp); } enable_irq(ite661x.client->irq); }
static void det_worker(struct work_struct *work) { int dat; char event_string[16]; char *envp[] = { event_string, NULL }; dev_dbg(&sii902x.pdev->dev, "%s\n", __func__); dat = i2c_smbus_read_byte_data(sii902x.client, 0x3D); if (dat & 0x1) { /* cable connection changes */ if (dat & 0x4) { sii902x.cable_plugin = 1; dev_dbg(&sii902x.pdev->dev, "EVENT=plugin\n"); sprintf(event_string, "EVENT=plugin"); if (sii902x_read_edid(sii902x.fbi) < 0) dev_err(&sii902x.client->dev, "Sii902x: read edid fail\n"); else { if (sii902x.fbi->monspecs.modedb_len > 0) { int i; const struct fb_videomode *mode; struct fb_videomode m; fb_destroy_modelist(&sii902x.fbi->modelist); for (i = 0; i < sii902x.fbi->monspecs.modedb_len; i++) { /*FIXME now we do not support interlaced mode */ mode = &sii902x.fbi->monspecs.modedb[i]; if (!(mode->vmode & FB_VMODE_INTERLACED)) { dev_dbg(&sii902x.pdev->dev, "Added mode %d:", i); dev_dbg(&sii902x.pdev->dev, "xres = %d, yres = %d, freq = %d, vmode = %d, flag = %d\n", mode->xres, mode->yres, mode->refresh, mode->vmode, mode->flag); fb_add_videomode(mode, &sii902x.fbi->modelist); } } fb_var_to_videomode(&m, &sii902x.fbi->var); dump_fb_videomode(&m); mode = fb_find_nearest_mode(&m, &sii902x.fbi->modelist); fb_videomode_to_var(&sii902x.fbi->var, mode); sii902x.fbi->var.activate |= FB_ACTIVATE_FORCE; console_lock(); sii902x.fbi->flags |= FBINFO_MISC_USEREVENT; fb_set_var(sii902x.fbi, &sii902x.fbi->var); sii902x.fbi->flags &= ~FBINFO_MISC_USEREVENT; console_unlock(); } /* Power on sii902x */ sii902x_poweron(); } } else { sii902x.cable_plugin = 0; dev_dbg(&sii902x.pdev->dev, "EVENT=plugout\n"); sprintf(event_string, "EVENT=plugout"); /* Power off sii902x */ sii902x_poweroff(); } kobject_uevent_env(&sii902x.pdev->dev.kobj, KOBJ_CHANGE, envp); } i2c_smbus_write_byte_data(sii902x.client, 0x3D, dat); dev_dbg(&sii902x.pdev->dev, "exit %s\n", __func__); }
/* * 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; }