18bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski/* 28bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * A framebuffer driver for VBE 2.0+ compliant video cards 38bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * 48bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * (c) 2007 Michal Januszewski <spock@gentoo.org> 58bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Loosely based upon the vesafb driver. 68bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * 78bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 88bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <linux/init.h> 98bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <linux/module.h> 108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <linux/moduleparam.h> 118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <linux/skbuff.h> 128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <linux/timer.h> 138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <linux/completion.h> 148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <linux/connector.h> 158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <linux/random.h> 168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <linux/platform_device.h> 178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <linux/limits.h> 188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <linux/fb.h> 198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <linux/io.h> 208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <linux/mutex.h> 215a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <video/edid.h> 238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <video/uvesafb.h> 248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#ifdef CONFIG_X86 258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <video/vga.h> 268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#endif 278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#ifdef CONFIG_MTRR 288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include <asm/mtrr.h> 298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#endif 308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#include "edid.h" 318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic struct cb_id uvesafb_cn_id = { 338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .idx = CN_IDX_V86D, 348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .val = CN_VAL_V86D_UVESAFB 358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski}; 368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic char v86d_path[PATH_MAX] = "/sbin/v86d"; 378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic char v86d_started; /* has v86d been started by uvesafb? */ 388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic struct fb_fix_screeninfo uvesafb_fix __devinitdata = { 408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .id = "VESA VGA", 418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .type = FB_TYPE_PACKED_PIXELS, 428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .accel = FB_ACCEL_NONE, 438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .visual = FB_VISUAL_TRUECOLOR, 448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski}; 458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int mtrr __devinitdata = 3; /* enable mtrr by default */ 4790ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool blank = 1; /* enable blanking by default */ 4879306a340c23e40c94ce16e504d172ae15b24187Sergio Luisstatic int ypan = 1; /* 0: scroll, 1: ypan, 2: ywrap */ 492ead9439f0c6ed03faafe27abe8bc1dd256d117bRusty Russellstatic bool pmi_setpal __devinitdata = true; /* use PMI for palette changes */ 5090ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool nocrtc __devinitdata; /* ignore CRTC settings */ 5190ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool noedid __devinitdata; /* don't try DDC transfers */ 528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int vram_remap __devinitdata; /* set amt. of memory to be used */ 538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int vram_total __devinitdata; /* set total amount of memory */ 548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic u16 maxclk __devinitdata; /* maximum pixel clock */ 558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic u16 maxvf __devinitdata; /* maximum vertical frequency */ 568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic u16 maxhf __devinitdata; /* maximum horizontal frequency */ 578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic u16 vbemode __devinitdata; /* force use of a specific VBE mode */ 588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic char *mode_option __devinitdata; 590ca1071f7dbd673de826eb3fb01bfdfd1d423433Michal Januszewskistatic u8 dac_width = 6; 608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic struct uvesafb_ktask *uvfb_tasks[UVESAFB_TASKS_MAX]; 628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic DEFINE_MUTEX(uvfb_lock); 638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski/* 658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * A handler for replies from userspace. 668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * 678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Make sure each message passes consistency checks and if it does, 688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * find the kernel part of the task struct, copy the registers and 698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * the buffer contents and then complete the task. 708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 717069331dbe7155f23966f5944109f909fea0c7e4Philipp Reisnerstatic void uvesafb_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) 728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_task *utask; 748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_ktask *task; 758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7638bf1953987c1735f3c9140fca762949a8cae507Eric W. Biederman if (!capable(CAP_SYS_ADMIN)) 77cc44578b5a508889beb8ae3ccd4d2bbdf17bc86cPhilipp Reisner return; 78cc44578b5a508889beb8ae3ccd4d2bbdf17bc86cPhilipp Reisner 798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (msg->seq >= UVESAFB_TASKS_MAX) 808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return; 818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mutex_lock(&uvfb_lock); 838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task = uvfb_tasks[msg->seq]; 848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!task || msg->ack != task->ack) { 868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mutex_unlock(&uvfb_lock); 878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return; 888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski utask = (struct uvesafb_task *)msg->data; 918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Sanity checks for the buffer length. */ 938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (task->t.buf_len < utask->buf_len || 948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski utask->buf_len > msg->len - sizeof(*utask)) { 958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mutex_unlock(&uvfb_lock); 968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return; 978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvfb_tasks[msg->seq] = NULL; 1008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mutex_unlock(&uvfb_lock); 1018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski memcpy(&task->t, utask, sizeof(*utask)); 1038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (task->t.buf_len && task->buf) 1058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski memcpy(task->buf, utask + 1, task->t.buf_len); 1068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski complete(task->done); 1088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return; 1098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 1108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int uvesafb_helper_start(void) 1128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 1138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski char *envp[] = { 1148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "HOME=/", 1158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "PATH=/sbin:/bin", 1168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski NULL, 1178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski }; 1188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski char *argv[] = { 1208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski v86d_path, 1218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski NULL, 1228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski }; 1238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12470834d3070c3f3015ab5c05176d54bd4a0100546Oleg Nesterov return call_usermodehelper(v86d_path, argv, envp, UMH_WAIT_PROC); 1258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 1268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski/* 1288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Execute a uvesafb task. 1298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * 1308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Returns 0 if the task is executed successfully. 1318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * 1328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * A message sent to the userspace consists of the uvesafb_task 1338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * struct and (optionally) a buffer. The uvesafb_task struct is 1348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * a simplified version of uvesafb_ktask (its kernel counterpart) 1358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * containing only the register values, flags and the length of 1368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * the buffer. 1378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * 1388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Each message is assigned a sequence number (increased linearly) 1398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * and a random ack number. The sequence number is used as a key 1408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * for the uvfb_tasks array which holds pointers to uvesafb_ktask 1418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * structs for all requests. 1428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 1438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int uvesafb_exec(struct uvesafb_ktask *task) 1448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 1458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski static int seq; 1468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct cn_msg *m; 1478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int err; 1488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int len = sizeof(task->t) + task->t.buf_len; 1498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 1518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Check whether the message isn't longer than the maximum 1528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * allowed by connector. 1538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 1548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (sizeof(*m) + len > CONNECTOR_MAX_MSG_SIZE) { 1558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_WARNING "uvesafb: message too long (%d), " 1568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "can't execute task\n", (int)(sizeof(*m) + len)); 1578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -E2BIG; 1588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 1598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski m = kzalloc(sizeof(*m) + len, GFP_KERNEL); 1618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!m) 1628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -ENOMEM; 1638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski init_completion(task->done); 1658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski memcpy(&m->id, &uvesafb_cn_id, sizeof(m->id)); 1678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski m->seq = seq; 1688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski m->len = len; 1698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski m->ack = random32(); 1708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* uvesafb_task structure */ 1728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski memcpy(m + 1, &task->t, sizeof(task->t)); 1738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Buffer */ 1758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski memcpy((u8 *)(m + 1) + sizeof(task->t), task->buf, task->t.buf_len); 1768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 1788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Save the message ack number so that we can find the kernel 1798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * part of this task when a reply is received from userspace. 1808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 1818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->ack = m->ack; 1828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mutex_lock(&uvfb_lock); 1848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* If all slots are taken -- bail out. */ 1868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (uvfb_tasks[seq]) { 1878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mutex_unlock(&uvfb_lock); 18860c1645dfac320e992bb5635887b7698ae6606bcAndrew Morton err = -EBUSY; 18960c1645dfac320e992bb5635887b7698ae6606bcAndrew Morton goto out; 1908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 1918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Save a pointer to the kernel part of the task struct. */ 1938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvfb_tasks[seq] = task; 1948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mutex_unlock(&uvfb_lock); 1958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1966e6fe42227e23a379d3c70f6ff257131399e4075Andrew Morton err = cn_netlink_send(m, 0, GFP_KERNEL); 1978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err == -ESRCH) { 1988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 1998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Try to start the userspace helper if sending 2008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * the request failed the first time. 2018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 2028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_helper_start(); 2038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err) { 2048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_ERR "uvesafb: failed to execute %s\n", 2058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski v86d_path); 2068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_ERR "uvesafb: make sure that the v86d " 2078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "helper is installed and executable\n"); 2088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else { 2098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski v86d_started = 1; 2108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = cn_netlink_send(m, 0, gfp_any()); 211ff491a7334acfd74e515c896632e37e401f52676Pablo Neira Ayuso if (err == -ENOBUFS) 212ff491a7334acfd74e515c896632e37e401f52676Pablo Neira Ayuso err = 0; 2138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 214ff491a7334acfd74e515c896632e37e401f52676Pablo Neira Ayuso } else if (err == -ENOBUFS) 215ff491a7334acfd74e515c896632e37e401f52676Pablo Neira Ayuso err = 0; 2168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 2178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!err && !(task->t.flags & TF_EXIT)) 2188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = !wait_for_completion_timeout(task->done, 2198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski msecs_to_jiffies(UVESAFB_TIMEOUT)); 2208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 2218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mutex_lock(&uvfb_lock); 2228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvfb_tasks[seq] = NULL; 2238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mutex_unlock(&uvfb_lock); 2248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 2258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski seq++; 2268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (seq >= UVESAFB_TASKS_MAX) 2278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski seq = 0; 22860c1645dfac320e992bb5635887b7698ae6606bcAndrew Mortonout: 22960c1645dfac320e992bb5635887b7698ae6606bcAndrew Morton kfree(m); 2308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return err; 2318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 2328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 2338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski/* 2348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Free a uvesafb_ktask struct. 2358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 2368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic void uvesafb_free(struct uvesafb_ktask *task) 2378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 2388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (task) { 2398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (task->done) 2408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski kfree(task->done); 2418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski kfree(task); 2428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 2438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 2448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 2458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski/* 2468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Prepare a uvesafb_ktask struct to be used again. 2478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 2488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic void uvesafb_reset(struct uvesafb_ktask *task) 2498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 2508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct completion *cpl = task->done; 2518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 2528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski memset(task, 0, sizeof(*task)); 2538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->done = cpl; 2548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 2558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 2568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski/* 2578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Allocate and prepare a uvesafb_ktask struct. 2588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 2598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic struct uvesafb_ktask *uvesafb_prep(void) 2608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 2618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_ktask *task; 2628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 2638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task = kzalloc(sizeof(*task), GFP_KERNEL); 2648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (task) { 2658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->done = kzalloc(sizeof(*task->done), GFP_KERNEL); 2668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!task->done) { 2678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski kfree(task); 2688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task = NULL; 2698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 2708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 2718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return task; 2728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 2738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 2748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic void uvesafb_setup_var(struct fb_var_screeninfo *var, 2758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info, struct vbe_mode_ib *mode) 2768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 2778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 2788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 2798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->vmode = FB_VMODE_NONINTERLACED; 2808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->sync = FB_SYNC_VERT_HIGH_ACT; 2818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 2828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->xres = mode->x_res; 2838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->yres = mode->y_res; 2848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->xres_virtual = mode->x_res; 2858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->yres_virtual = (par->ypan) ? 2868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->fix.smem_len / mode->bytes_per_scan_line : 2878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode->y_res; 2888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->xoffset = 0; 2898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->yoffset = 0; 2908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->bits_per_pixel = mode->bits_per_pixel; 2918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 2928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (var->bits_per_pixel == 15) 2938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->bits_per_pixel = 16; 2948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 2958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (var->bits_per_pixel > 8) { 2968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->red.offset = mode->red_off; 2978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->red.length = mode->red_len; 2988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->green.offset = mode->green_off; 2998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->green.length = mode->green_len; 3008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->blue.offset = mode->blue_off; 3018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->blue.length = mode->blue_len; 3028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->transp.offset = mode->rsvd_off; 3038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->transp.length = mode->rsvd_len; 3048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else { 3058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->red.offset = 0; 3068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->green.offset = 0; 3078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->blue.offset = 0; 3088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->transp.offset = 0; 3098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3100ca1071f7dbd673de826eb3fb01bfdfd1d423433Michal Januszewski var->red.length = 8; 3110ca1071f7dbd673de826eb3fb01bfdfd1d423433Michal Januszewski var->green.length = 8; 3120ca1071f7dbd673de826eb3fb01bfdfd1d423433Michal Januszewski var->blue.length = 8; 3130ca1071f7dbd673de826eb3fb01bfdfd1d423433Michal Januszewski var->transp.length = 0; 3148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 3158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 3168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int uvesafb_vbe_find_mode(struct uvesafb_par *par, 3188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int xres, int yres, int depth, unsigned char flags) 3198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 3208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int i, match = -1, h = 0, d = 0x7fffffff; 3218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski for (i = 0; i < par->vbe_modes_cnt; i++) { 3238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski h = abs(par->vbe_modes[i].x_res - xres) + 3248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski abs(par->vbe_modes[i].y_res - yres) + 3258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski abs(depth - par->vbe_modes[i].depth); 3268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 3288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * We have an exact match in terms of resolution 3298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * and depth. 3308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 3318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (h == 0) 3328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return i; 3338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (h < d || (h == d && par->vbe_modes[i].depth > depth)) { 3358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski d = h; 3368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski match = i; 3378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 3388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 3398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski i = 1; 3408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (flags & UVESAFB_EXACT_DEPTH && 3428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->vbe_modes[match].depth != depth) 3438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski i = 0; 3448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (flags & UVESAFB_EXACT_RES && d > 24) 3468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski i = 0; 3478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (i != 0) 3498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return match; 3508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else 3518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -1; 3528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 3538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic u8 *uvesafb_vbe_state_save(struct uvesafb_par *par) 3558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 3568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_ktask *task; 3578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski u8 *state; 3588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int err; 3598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!par->vbe_state_size) 3618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return NULL; 3628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski state = kmalloc(par->vbe_state_size, GFP_KERNEL); 3648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!state) 365c2bc0a756b1f98bd712fabe78eb49d7d5ae72075Wang YanQing return ERR_PTR(-ENOMEM); 3668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task = uvesafb_prep(); 3688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!task) { 3698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski kfree(state); 3708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return NULL; 3718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 3728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax = 0x4f04; 3748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ecx = 0x000f; 3758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.edx = 0x0001; 3768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.flags = TF_BUF_RET | TF_BUF_ESBX; 3778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.buf_len = par->vbe_state_size; 3788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->buf = state; 3798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_exec(task); 3808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err || (task->t.regs.eax & 0xffff) != 0x004f) { 3828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_WARNING "uvesafb: VBE get state call " 3838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "failed (eax=0x%x, err=%d)\n", 3848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax, err); 3858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski kfree(state); 3868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski state = NULL; 3878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 3888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_free(task); 3908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return state; 3918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 3928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic void uvesafb_vbe_state_restore(struct uvesafb_par *par, u8 *state_buf) 3948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 3958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_ktask *task; 3968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int err; 3978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 3988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!state_buf) 3998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return; 4008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task = uvesafb_prep(); 4028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!task) 4038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return; 4048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax = 0x4f04; 4068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ecx = 0x000f; 4078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.edx = 0x0002; 4088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.buf_len = par->vbe_state_size; 4098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.flags = TF_BUF_ESBX; 4108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->buf = state_buf; 4118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_exec(task); 4138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err || (task->t.regs.eax & 0xffff) != 0x004f) 4148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_WARNING "uvesafb: VBE state restore call " 4158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "failed (eax=0x%x, err=%d)\n", 4168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax, err); 4178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_free(task); 4198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 4208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int __devinit uvesafb_vbe_getinfo(struct uvesafb_ktask *task, 4228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par) 4238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 4248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int err; 4258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax = 0x4f00; 4278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.flags = TF_VBEIB; 4288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.buf_len = sizeof(struct vbe_ib); 4298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->buf = &par->vbe_ib; 4308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski strncpy(par->vbe_ib.vbe_signature, "VBE2", 4); 4318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_exec(task); 4338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err || (task->t.regs.eax & 0xffff) != 0x004f) { 4348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_ERR "uvesafb: Getting VBE info block failed " 4358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "(eax=0x%x, err=%d)\n", (u32)task->t.regs.eax, 4368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err); 4378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -EINVAL; 4388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 4398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_ib.vbe_version < 0x0200) { 4418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_ERR "uvesafb: Sorry, pre-VBE 2.0 cards are " 4428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "not supported.\n"); 4438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -EINVAL; 4448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 4458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!par->vbe_ib.mode_list_ptr) { 4478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_ERR "uvesafb: Missing mode list!\n"); 4488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -EINVAL; 4498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 4508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO "uvesafb: "); 4528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 4548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Convert string pointers and the mode list pointer into 4558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * usable addresses. Print informational messages about the 4568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * video adapter and its vendor. 4578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 4588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_ib.oem_vendor_name_ptr) 4598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk("%s, ", 4608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ((char *)task->buf) + par->vbe_ib.oem_vendor_name_ptr); 4618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_ib.oem_product_name_ptr) 4638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk("%s, ", 4648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ((char *)task->buf) + par->vbe_ib.oem_product_name_ptr); 4658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_ib.oem_product_rev_ptr) 4678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk("%s, ", 4688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ((char *)task->buf) + par->vbe_ib.oem_product_rev_ptr); 4698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_ib.oem_string_ptr) 4718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk("OEM: %s, ", 4728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ((char *)task->buf) + par->vbe_ib.oem_string_ptr); 4738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk("VBE v%d.%d\n", ((par->vbe_ib.vbe_version & 0xff00) >> 8), 4758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->vbe_ib.vbe_version & 0xff); 4768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 4788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 4798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task, 4818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par) 4828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 4838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int off = 0, err; 4848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski u16 *mode; 4858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->vbe_modes_cnt = 0; 4878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Count available modes. */ 4898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode = (u16 *) (((u8 *)&par->vbe_ib) + par->vbe_ib.mode_list_ptr); 4908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski while (*mode != 0xffff) { 4918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->vbe_modes_cnt++; 4928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode++; 4938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 4948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 4958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->vbe_modes = kzalloc(sizeof(struct vbe_mode_ib) * 4968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->vbe_modes_cnt, GFP_KERNEL); 4978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!par->vbe_modes) 4988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -ENOMEM; 4998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 5008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Get info about all available modes. */ 5018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode = (u16 *) (((u8 *)&par->vbe_ib) + par->vbe_ib.mode_list_ptr); 5028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski while (*mode != 0xffff) { 5038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct vbe_mode_ib *mib; 5048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 5058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_reset(task); 5068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax = 0x4f01; 5078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ecx = (u32) *mode; 5088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.flags = TF_BUF_RET | TF_BUF_ESDI; 5098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.buf_len = sizeof(struct vbe_mode_ib); 5108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->buf = par->vbe_modes + off; 5118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 5128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_exec(task); 5138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err || (task->t.regs.eax & 0xffff) != 0x004f) { 5149350cc90ca8a72bc1974f76a9922f91ced84a5cfMichal Januszewski printk(KERN_WARNING "uvesafb: Getting mode info block " 5158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "for mode 0x%x failed (eax=0x%x, err=%d)\n", 5168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski *mode, (u32)task->t.regs.eax, err); 5179350cc90ca8a72bc1974f76a9922f91ced84a5cfMichal Januszewski mode++; 5189350cc90ca8a72bc1974f76a9922f91ced84a5cfMichal Januszewski par->vbe_modes_cnt--; 5199350cc90ca8a72bc1974f76a9922f91ced84a5cfMichal Januszewski continue; 5208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 5218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 5228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mib = task->buf; 5238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mib->mode_id = *mode; 5248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 5258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 5268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * We only want modes that are supported with the current 5278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * hardware configuration, color, graphics and that have 5288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * support for the LFB. 5298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 5308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if ((mib->mode_attr & VBE_MODE_MASK) == VBE_MODE_MASK && 5318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mib->bits_per_pixel >= 8) 5328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski off++; 5338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else 5348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->vbe_modes_cnt--; 5358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 5368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode++; 5378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mib->depth = mib->red_len + mib->green_len + mib->blue_len; 5388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 5398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 5408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Handle 8bpp modes and modes with broken color component 5418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * lengths. 5428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 5438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (mib->depth == 0 || (mib->depth == 24 && 5448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mib->bits_per_pixel == 32)) 5458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mib->depth = mib->bits_per_pixel; 5468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 5478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 5489350cc90ca8a72bc1974f76a9922f91ced84a5cfMichal Januszewski if (par->vbe_modes_cnt > 0) 5499350cc90ca8a72bc1974f76a9922f91ced84a5cfMichal Januszewski return 0; 5509350cc90ca8a72bc1974f76a9922f91ced84a5cfMichal Januszewski else 5519350cc90ca8a72bc1974f76a9922f91ced84a5cfMichal Januszewski return -EINVAL; 5528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 5538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 5548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski/* 5558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * The Protected Mode Interface is 32-bit x86 code, so we only run it on 5568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * x86 and not x86_64. 5578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 5588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#ifdef CONFIG_X86_32 5598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int __devinit uvesafb_vbe_getpmi(struct uvesafb_ktask *task, 5608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par) 5618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 5628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int i, err; 5638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 5648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_reset(task); 5658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax = 0x4f0a; 5668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ebx = 0x0; 5678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_exec(task); 5688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 5698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if ((task->t.regs.eax & 0xffff) != 0x4f || task->t.regs.es < 0xc000) { 5708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->pmi_setpal = par->ypan = 0; 5718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else { 5728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->pmi_base = (u16 *)phys_to_virt(((u32)task->t.regs.es << 4) 5738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski + task->t.regs.edi); 5748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->pmi_start = (u8 *)par->pmi_base + par->pmi_base[1]; 5758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->pmi_pal = (u8 *)par->pmi_base + par->pmi_base[2]; 5768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO "uvesafb: protected mode interface info at " 5778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "%04x:%04x\n", 5788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski (u16)task->t.regs.es, (u16)task->t.regs.edi); 5798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO "uvesafb: pmi: set display start = %p, " 5808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "set palette = %p\n", par->pmi_start, 5818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->pmi_pal); 5828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 5838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->pmi_base[3]) { 5848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO "uvesafb: pmi: ports = "); 5858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski for (i = par->pmi_base[3]/2; 5868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->pmi_base[i] != 0xffff; i++) 5878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk("%x ", par->pmi_base[i]); 5888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk("\n"); 5898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 5908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->pmi_base[i] != 0xffff) { 5918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO "uvesafb: can't handle memory" 5928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski " requests, pmi disabled\n"); 5938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->ypan = par->pmi_setpal = 0; 5948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 5958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 5968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 5978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 5988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 5998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#endif /* CONFIG_X86_32 */ 6008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski/* 6028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Check whether a video mode is supported by the Video BIOS and is 6038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * compatible with the monitor limits. 6048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 6058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int __devinit uvesafb_is_valid_mode(struct fb_videomode *mode, 6068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info) 6078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 6088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (info->monspecs.gtf) { 6098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_videomode_to_var(&info->var, mode); 6108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (fb_validate_mode(&info->var, info)) 6118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 6128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 6138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (uvesafb_vbe_find_mode(info->par, mode->xres, mode->yres, 8, 6158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski UVESAFB_EXACT_RES) == -1) 6168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 6178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 1; 6198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 6208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int __devinit uvesafb_vbe_getedid(struct uvesafb_ktask *task, 6228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info) 6238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 6248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 6258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int err = 0; 6268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (noedid || par->vbe_ib.vbe_version < 0x0300) 6288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -EINVAL; 6298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax = 0x4f15; 6318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ebx = 0; 6328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ecx = 0; 6338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.buf_len = 0; 6348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.flags = 0; 6358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_exec(task); 6378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if ((task->t.regs.eax & 0xffff) != 0x004f || err) 6398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -EINVAL; 6408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if ((task->t.regs.ebx & 0x3) == 3) { 6428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO "uvesafb: VBIOS/hardware supports both " 6438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "DDC1 and DDC2 transfers\n"); 6448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else if ((task->t.regs.ebx & 0x3) == 2) { 6458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO "uvesafb: VBIOS/hardware supports DDC2 " 6468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "transfers\n"); 6478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else if ((task->t.regs.ebx & 0x3) == 1) { 6488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO "uvesafb: VBIOS/hardware supports DDC1 " 6498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "transfers\n"); 6508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else { 6518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO "uvesafb: VBIOS/hardware doesn't support " 6528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "DDC transfers\n"); 6538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -EINVAL; 6548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 6558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax = 0x4f15; 6578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ebx = 1; 6588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ecx = task->t.regs.edx = 0; 6598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.flags = TF_BUF_RET | TF_BUF_ESDI; 6608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.buf_len = EDID_LENGTH; 6618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->buf = kzalloc(EDID_LENGTH, GFP_KERNEL); 6628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_exec(task); 6648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if ((task->t.regs.eax & 0xffff) == 0x004f && !err) { 6668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_edid_to_monspecs(task->buf, &info->monspecs); 6678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (info->monspecs.vfmax && info->monspecs.hfmax) { 6698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 6708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * If the maximum pixel clock wasn't specified in 6718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * the EDID block, set it to 300 MHz. 6728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 6738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (info->monspecs.dclkmax == 0) 6748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->monspecs.dclkmax = 300 * 1000000; 6758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->monspecs.gtf = 1; 6768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 6778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else { 6788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = -EINVAL; 6798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 6808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski kfree(task->buf); 6828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return err; 6838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 6848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic void __devinit uvesafb_vbe_getmonspecs(struct uvesafb_ktask *task, 6868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info) 6878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 6888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 6898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int i; 6908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski memset(&info->monspecs, 0, sizeof(info->monspecs)); 6928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 6938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 6948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * If we don't get all necessary data from the EDID block, 6958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * mark it as incompatible with the GTF and set nocrtc so 6968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * that we always use the default BIOS refresh rate. 6978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 6988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (uvesafb_vbe_getedid(task, info)) { 6998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->monspecs.gtf = 0; 7008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->nocrtc = 1; 7018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 7028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Kernel command line overrides. */ 7048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (maxclk) 7058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->monspecs.dclkmax = maxclk * 1000000; 7068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (maxvf) 7078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->monspecs.vfmax = maxvf; 7088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (maxhf) 7098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->monspecs.hfmax = maxhf * 1000; 7108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 7128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * In case DDC transfers are not supported, the user can provide 7138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * monitor limits manually. Lower limits are set to "safe" values. 7148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 7158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (info->monspecs.gtf == 0 && maxclk && maxvf && maxhf) { 7168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->monspecs.dclkmin = 0; 7178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->monspecs.vfmin = 60; 7188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->monspecs.hfmin = 29000; 7198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->monspecs.gtf = 1; 7208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->nocrtc = 0; 7218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 7228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (info->monspecs.gtf) 7248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO 7258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "uvesafb: monitor limits: vf = %d Hz, hf = %d kHz, " 7268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "clk = %d MHz\n", info->monspecs.vfmax, 7278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski (int)(info->monspecs.hfmax / 1000), 7288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski (int)(info->monspecs.dclkmax / 1000000)); 7298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else 7308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO "uvesafb: no monitor limits have been set, " 7318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "default refresh rate will be used\n"); 7328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Add VBE modes to the modelist. */ 7348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski for (i = 0; i < par->vbe_modes_cnt; i++) { 7358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_var_screeninfo var; 7368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct vbe_mode_ib *mode; 7378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_videomode vmode; 7388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode = &par->vbe_modes[i]; 7408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski memset(&var, 0, sizeof(var)); 7418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var.xres = mode->x_res; 7438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var.yres = mode->y_res; 7448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, &var, info); 7468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_var_to_videomode(&vmode, &var); 7478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_add_videomode(&vmode, &info->modelist); 7488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 7498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Add valid VESA modes to our modelist. */ 7518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski for (i = 0; i < VESA_MODEDB_SIZE; i++) { 7528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (uvesafb_is_valid_mode((struct fb_videomode *) 7538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski &vesa_modes[i], info)) 7548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_add_videomode(&vesa_modes[i], &info->modelist); 7558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 7568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski for (i = 0; i < info->monspecs.modedb_len; i++) { 7588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (uvesafb_is_valid_mode(&info->monspecs.modedb[i], info)) 7598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_add_videomode(&info->monspecs.modedb[i], 7608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski &info->modelist); 7618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 7628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return; 7648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 7658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic void __devinit uvesafb_vbe_getstatesize(struct uvesafb_ktask *task, 7678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par) 7688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 7698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int err; 7708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_reset(task); 7728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 7748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Get the VBE state buffer size. We want all available 7758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * hardware state data (CL = 0x0f). 7768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 7778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax = 0x4f04; 7788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ecx = 0x000f; 7798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.edx = 0x0000; 7808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.flags = 0; 7818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_exec(task); 7838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err || (task->t.regs.eax & 0xffff) != 0x004f) { 7858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_WARNING "uvesafb: VBE state buffer size " 7868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "cannot be determined (eax=0x%x, err=%d)\n", 7878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax, err); 7888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->vbe_state_size = 0; 7898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return; 7908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 7918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->vbe_state_size = 64 * (task->t.regs.ebx & 0xffff); 7938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 7948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 7958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int __devinit uvesafb_vbe_init(struct fb_info *info) 7968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 7978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_ktask *task = NULL; 7988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 7998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int err; 8008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 8018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task = uvesafb_prep(); 8028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!task) 8038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -ENOMEM; 8048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 8058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_vbe_getinfo(task, par); 8068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err) 8078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski goto out; 8088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 8098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_vbe_getmodes(task, par); 8108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err) 8118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski goto out; 8128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 8138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->nocrtc = nocrtc; 8148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#ifdef CONFIG_X86_32 8158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->pmi_setpal = pmi_setpal; 8168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->ypan = ypan; 8178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 818b78f29ca0516266431688c5eb42d39ce42ec039aWang YanQing if (par->pmi_setpal || par->ypan) { 819b78f29ca0516266431688c5eb42d39ce42ec039aWang YanQing if (__supported_pte_mask & _PAGE_NX) { 820b78f29ca0516266431688c5eb42d39ce42ec039aWang YanQing par->pmi_setpal = par->ypan = 0; 821b78f29ca0516266431688c5eb42d39ce42ec039aWang YanQing printk(KERN_WARNING "uvesafb: NX protection is actively." 822b78f29ca0516266431688c5eb42d39ce42ec039aWang YanQing "We have better not to use the PMI.\n"); 823b78f29ca0516266431688c5eb42d39ce42ec039aWang YanQing } else { 824b78f29ca0516266431688c5eb42d39ce42ec039aWang YanQing uvesafb_vbe_getpmi(task, par); 825b78f29ca0516266431688c5eb42d39ce42ec039aWang YanQing } 826b78f29ca0516266431688c5eb42d39ce42ec039aWang YanQing } 8278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#else 8288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* The protected mode interface is not available on non-x86. */ 8298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->pmi_setpal = par->ypan = 0; 8308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#endif 8318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 8328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski INIT_LIST_HEAD(&info->modelist); 8338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_vbe_getmonspecs(task, info); 8348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_vbe_getstatesize(task, par); 8358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 8368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskiout: uvesafb_free(task); 8378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return err; 8388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 8398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 8408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int __devinit uvesafb_vbe_init_mode(struct fb_info *info) 8418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 8428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct list_head *pos; 8438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_modelist *modelist; 8448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_videomode *mode; 8458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 8468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int i, modeid; 8478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 8488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Has the user requested a specific VESA mode? */ 8498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (vbemode) { 8508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski for (i = 0; i < par->vbe_modes_cnt; i++) { 8518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_modes[i].mode_id == vbemode) { 85223b736545473ed853b685cbc03883aa6ff3f0e0dMichal Januszewski modeid = i; 85323b736545473ed853b685cbc03883aa6ff3f0e0dMichal Januszewski uvesafb_setup_var(&info->var, info, 85423b736545473ed853b685cbc03883aa6ff3f0e0dMichal Januszewski &par->vbe_modes[modeid]); 8558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, 85623b736545473ed853b685cbc03883aa6ff3f0e0dMichal Januszewski &info->var, info); 8578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 8588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * With pixclock set to 0, the default BIOS 8598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * timings will be used in set_par(). 8608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 8618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->var.pixclock = 0; 8628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski goto gotmode; 8638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 8648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 8658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO "uvesafb: requested VBE mode 0x%x is " 8668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "unavailable\n", vbemode); 8678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski vbemode = 0; 8688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 8698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 8708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Count the modes in the modelist */ 8718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski i = 0; 8728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski list_for_each(pos, &info->modelist) 8738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski i++; 8748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 8758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 8768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Convert the modelist into a modedb so that we can use it with 8778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * fb_find_mode(). 8788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 8798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode = kzalloc(i * sizeof(*mode), GFP_KERNEL); 8808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (mode) { 8818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski i = 0; 8828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski list_for_each(pos, &info->modelist) { 8838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski modelist = list_entry(pos, struct fb_modelist, list); 8848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode[i] = modelist->mode; 8858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski i++; 8868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 8878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 8888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!mode_option) 8898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode_option = UVESAFB_DEFAULT_MODE; 8908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 8918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski i = fb_find_mode(&info->var, info, mode_option, mode, i, 8928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski NULL, 8); 8938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 8948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski kfree(mode); 8958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 8968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 8978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* fb_find_mode() failed */ 8985e72b32d86841e4a4a3045d8e35a39eb53ce7ce2Michal Januszewski if (i == 0) { 8998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->var.xres = 640; 9008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->var.yres = 480; 9018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode = (struct fb_videomode *) 9028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_find_best_mode(&info->var, &info->modelist); 9038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 9048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (mode) { 9058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_videomode_to_var(&info->var, mode); 9068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else { 9078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski modeid = par->vbe_modes[0].mode_id; 90823b736545473ed853b685cbc03883aa6ff3f0e0dMichal Januszewski uvesafb_setup_var(&info->var, info, 90923b736545473ed853b685cbc03883aa6ff3f0e0dMichal Januszewski &par->vbe_modes[modeid]); 9108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, 91123b736545473ed853b685cbc03883aa6ff3f0e0dMichal Januszewski &info->var, info); 91223b736545473ed853b685cbc03883aa6ff3f0e0dMichal Januszewski 9138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski goto gotmode; 9148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 9158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 9168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 9178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Look for a matching VBE mode. */ 9188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski modeid = uvesafb_vbe_find_mode(par, info->var.xres, info->var.yres, 9198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->var.bits_per_pixel, UVESAFB_EXACT_RES); 9208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 9218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (modeid == -1) 9228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -EINVAL; 9238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 9248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_setup_var(&info->var, info, &par->vbe_modes[modeid]); 9258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 92623b736545473ed853b685cbc03883aa6ff3f0e0dMichal Januszewskigotmode: 9278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 9288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * If we are not VBE3.0+ compliant, we're done -- the BIOS will 9298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * ignore our timings anyway. 9308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 9318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_ib.vbe_version < 0x0300 || par->nocrtc) 9328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, 9338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski &info->var, info); 9348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 9358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return modeid; 9368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 9378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 9388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int uvesafb_setpalette(struct uvesafb_pal_entry *entries, int count, 9398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int start, struct fb_info *info) 9408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 9418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_ktask *task; 94203ad369ac900116f35da7505f768ebbd481d09a4Frank Lichtenheld#ifdef CONFIG_X86 9438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 9448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int i = par->mode_idx; 94503ad369ac900116f35da7505f768ebbd481d09a4Frank Lichtenheld#endif 9468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int err = 0; 9478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 9488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 9498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * We support palette modifications for 8 bpp modes only, so 9508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * there can never be more than 256 entries. 9518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 9528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (start + count > 256) 9538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -EINVAL; 9548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 9558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#ifdef CONFIG_X86 9568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Use VGA registers if mode is VGA-compatible. */ 9578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (i >= 0 && i < par->vbe_modes_cnt && 9588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->vbe_modes[i].mode_attr & VBE_MODE_VGACOMPAT) { 9598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski for (i = 0; i < count; i++) { 9608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski outb_p(start + i, dac_reg); 9618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski outb_p(entries[i].red, dac_val); 9628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski outb_p(entries[i].green, dac_val); 9638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski outb_p(entries[i].blue, dac_val); 9648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 9658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 9668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#ifdef CONFIG_X86_32 9678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (par->pmi_setpal) { 9688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski __asm__ __volatile__( 9698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "call *(%%esi)" 9708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski : /* no return value */ 9718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski : "a" (0x4f09), /* EAX */ 9728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "b" (0), /* EBX */ 9738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "c" (count), /* ECX */ 9748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "d" (start), /* EDX */ 9758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "D" (entries), /* EDI */ 9768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "S" (&par->pmi_pal)); /* ESI */ 9778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 9788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#endif /* CONFIG_X86_32 */ 9798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else 9808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#endif /* CONFIG_X86 */ 9818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski { 9828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task = uvesafb_prep(); 9838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!task) 9848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -ENOMEM; 9858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 9868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax = 0x4f09; 9878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ebx = 0x0; 9888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ecx = count; 9898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.edx = start; 9908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.flags = TF_BUF_ESDI; 9918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.buf_len = sizeof(struct uvesafb_pal_entry) * count; 9928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->buf = entries; 9938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 9948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_exec(task); 9958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if ((task->t.regs.eax & 0xffff) != 0x004f) 9968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = 1; 9978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 9988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_free(task); 9998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 10008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return err; 10018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 10028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 10038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int uvesafb_setcolreg(unsigned regno, unsigned red, unsigned green, 10048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski unsigned blue, unsigned transp, 10058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info) 10068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 10078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_pal_entry entry; 10080ca1071f7dbd673de826eb3fb01bfdfd1d423433Michal Januszewski int shift = 16 - dac_width; 10098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int err = 0; 10108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 10118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (regno >= info->cmap.len) 10128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -EINVAL; 10138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 10148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (info->var.bits_per_pixel == 8) { 10158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski entry.red = red >> shift; 10168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski entry.green = green >> shift; 10178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski entry.blue = blue >> shift; 10188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski entry.pad = 0; 10198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 10208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_setpalette(&entry, 1, regno, info); 10218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else if (regno < 16) { 10228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski switch (info->var.bits_per_pixel) { 10238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski case 16: 10248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (info->var.red.offset == 10) { 10258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 1:5:5:5 */ 10268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ((u32 *) (info->pseudo_palette))[regno] = 10278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ((red & 0xf800) >> 1) | 10288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ((green & 0xf800) >> 6) | 10298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ((blue & 0xf800) >> 11); 10308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else { 10318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 0:5:6:5 */ 10328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ((u32 *) (info->pseudo_palette))[regno] = 10338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ((red & 0xf800) ) | 10348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ((green & 0xfc00) >> 5) | 10358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ((blue & 0xf800) >> 11); 10368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 10378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski break; 10388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 10398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski case 24: 10408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski case 32: 10418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski red >>= 8; 10428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski green >>= 8; 10438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski blue >>= 8; 10448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ((u32 *)(info->pseudo_palette))[regno] = 10458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski (red << info->var.red.offset) | 10468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski (green << info->var.green.offset) | 10478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski (blue << info->var.blue.offset); 10488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski break; 10498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 10508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 10518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return err; 10528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 10538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 10548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int uvesafb_setcmap(struct fb_cmap *cmap, struct fb_info *info) 10558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 10568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_pal_entry *entries; 10570ca1071f7dbd673de826eb3fb01bfdfd1d423433Michal Januszewski int shift = 16 - dac_width; 10588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int i, err = 0; 10598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 10608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (info->var.bits_per_pixel == 8) { 10618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (cmap->start + cmap->len > info->cmap.start + 10628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->cmap.len || cmap->start < info->cmap.start) 10638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -EINVAL; 10648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 10658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski entries = kmalloc(sizeof(*entries) * cmap->len, GFP_KERNEL); 10668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!entries) 10678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -ENOMEM; 10688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 10698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski for (i = 0; i < cmap->len; i++) { 10708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski entries[i].red = cmap->red[i] >> shift; 10718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski entries[i].green = cmap->green[i] >> shift; 10728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski entries[i].blue = cmap->blue[i] >> shift; 10738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski entries[i].pad = 0; 10748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 10758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_setpalette(entries, cmap->len, cmap->start, info); 10768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski kfree(entries); 10778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else { 10788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 10798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * For modes with bpp > 8, we only set the pseudo palette in 10808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * the fb_info struct. We rely on uvesafb_setcolreg to do all 10818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * sanity checking. 10828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 10838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski for (i = 0; i < cmap->len; i++) { 10848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err |= uvesafb_setcolreg(cmap->start + i, cmap->red[i], 10858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski cmap->green[i], cmap->blue[i], 10868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 0, info); 10878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 10888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 10898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return err; 10908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 10918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 10928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int uvesafb_pan_display(struct fb_var_screeninfo *var, 10938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info) 10948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 10958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#ifdef CONFIG_X86_32 10968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int offset; 10978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 10988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 10998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4; 11008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 11018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 11028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * It turns out it's not the best idea to do panning via vm86, 11038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * so we only allow it if we have a PMI. 11048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 11058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->pmi_start) { 11068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski __asm__ __volatile__( 11078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "call *(%%edi)" 11088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski : /* no return value */ 11098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski : "a" (0x4f07), /* EAX */ 11108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "b" (0), /* EBX */ 11118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "c" (offset), /* ECX */ 11128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "d" (offset >> 16), /* EDX */ 11138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "D" (&par->pmi_start)); /* EDI */ 11148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 11158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#endif 11168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 11178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 11188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 11198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int uvesafb_blank(int blank, struct fb_info *info) 11208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 11218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_ktask *task; 11228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int err = 1; 11238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#ifdef CONFIG_X86 112403ad369ac900116f35da7505f768ebbd481d09a4Frank Lichtenheld struct uvesafb_par *par = info->par; 112503ad369ac900116f35da7505f768ebbd481d09a4Frank Lichtenheld 11268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_ib.capabilities & VBE_CAP_VGACOMPAT) { 11278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int loop = 10000; 11288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski u8 seq = 0, crtc17 = 0; 11298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 11308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (blank == FB_BLANK_POWERDOWN) { 11318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski seq = 0x20; 11328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc17 = 0x00; 11338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = 0; 11348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else { 11358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski seq = 0x00; 11368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc17 = 0x80; 11378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = (blank == FB_BLANK_UNBLANK) ? 0 : -EINVAL; 11388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 11398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 11408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski vga_wseq(NULL, 0x00, 0x01); 11418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski seq |= vga_rseq(NULL, 0x01) & ~0x20; 11428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski vga_wseq(NULL, 0x00, seq); 11438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 11448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc17 |= vga_rcrt(NULL, 0x17) & ~0x80; 11458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski while (loop--); 11468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski vga_wcrt(NULL, 0x17, crtc17); 11478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski vga_wseq(NULL, 0x00, 0x03); 11488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else 11498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#endif /* CONFIG_X86 */ 11508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski { 11518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task = uvesafb_prep(); 11528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!task) 11538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -ENOMEM; 11548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 11558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax = 0x4f10; 11568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski switch (blank) { 11578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski case FB_BLANK_UNBLANK: 11588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ebx = 0x0001; 11598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski break; 11608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski case FB_BLANK_NORMAL: 11618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ebx = 0x0101; /* standby */ 11628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski break; 11638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski case FB_BLANK_POWERDOWN: 11648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ebx = 0x0401; /* powerdown */ 11658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski break; 11668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski default: 11678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski goto out; 11688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 11698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 11708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_exec(task); 11718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err || (task->t.regs.eax & 0xffff) != 0x004f) 11728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = 1; 11738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskiout: uvesafb_free(task); 11748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 11758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return err; 11768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 11778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 11788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int uvesafb_open(struct fb_info *info, int user) 11798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 11808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 11818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int cnt = atomic_read(&par->ref_count); 1182c2bc0a756b1f98bd712fabe78eb49d7d5ae72075Wang YanQing u8 *buf = NULL; 11838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1184c2bc0a756b1f98bd712fabe78eb49d7d5ae72075Wang YanQing if (!cnt && par->vbe_state_size) { 1185c2bc0a756b1f98bd712fabe78eb49d7d5ae72075Wang YanQing buf = uvesafb_vbe_state_save(par); 1186c2bc0a756b1f98bd712fabe78eb49d7d5ae72075Wang YanQing if (IS_ERR(buf)) { 1187c2bc0a756b1f98bd712fabe78eb49d7d5ae72075Wang YanQing printk(KERN_WARNING "uvesafb: save hardware state" 1188c2bc0a756b1f98bd712fabe78eb49d7d5ae72075Wang YanQing "failed, error code is %ld!\n", PTR_ERR(buf)); 1189c2bc0a756b1f98bd712fabe78eb49d7d5ae72075Wang YanQing } else { 1190c2bc0a756b1f98bd712fabe78eb49d7d5ae72075Wang YanQing par->vbe_state_orig = buf; 1191c2bc0a756b1f98bd712fabe78eb49d7d5ae72075Wang YanQing } 1192c2bc0a756b1f98bd712fabe78eb49d7d5ae72075Wang YanQing } 11938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 11948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski atomic_inc(&par->ref_count); 11958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 11968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 11978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 11988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int uvesafb_release(struct fb_info *info, int user) 11998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 12008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_ktask *task = NULL; 12018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 12028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int cnt = atomic_read(&par->ref_count); 12038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!cnt) 12058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -EINVAL; 12068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (cnt != 1) 12088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski goto out; 12098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task = uvesafb_prep(); 12118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!task) 12128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski goto out; 12138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* First, try to set the standard 80x25 text mode. */ 12158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax = 0x0003; 12168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_exec(task); 12178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 12198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Now try to restore whatever hardware state we might have 12208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * saved when the fb device was first opened. 12218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 12228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_vbe_state_restore(par, par->vbe_state_orig); 12238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskiout: 12248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski atomic_dec(&par->ref_count); 12258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (task) 12268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_free(task); 12278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 12288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 12298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int uvesafb_set_par(struct fb_info *info) 12318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 12328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 12338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_ktask *task = NULL; 12348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct vbe_crtc_ib *crtc = NULL; 12358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct vbe_mode_ib *mode = NULL; 12368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int i, err = 0, depth = info->var.bits_per_pixel; 12378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (depth > 8 && depth != 32) 12398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski depth = info->var.red.length + info->var.green.length + 12408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->var.blue.length; 12418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski i = uvesafb_vbe_find_mode(par, info->var.xres, info->var.yres, depth, 12438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski UVESAFB_EXACT_RES | UVESAFB_EXACT_DEPTH); 12448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (i >= 0) 12458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode = &par->vbe_modes[i]; 12468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else 12478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -EINVAL; 12488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task = uvesafb_prep(); 12508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!task) 12518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -ENOMEM; 12528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskisetmode: 12538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax = 0x4f02; 12548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ebx = mode->mode_id | 0x4000; /* use LFB */ 12558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_ib.vbe_version >= 0x0300 && !par->nocrtc && 12578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->var.pixclock != 0) { 12588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ebx |= 0x0800; /* use CRTC data */ 12598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.flags = TF_BUF_ESDI; 12608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc = kzalloc(sizeof(struct vbe_crtc_ib), GFP_KERNEL); 12618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!crtc) { 12628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = -ENOMEM; 12638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski goto out; 12648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 12658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc->horiz_start = info->var.xres + info->var.right_margin; 12668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc->horiz_end = crtc->horiz_start + info->var.hsync_len; 12678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc->horiz_total = crtc->horiz_end + info->var.left_margin; 12688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc->vert_start = info->var.yres + info->var.lower_margin; 12708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc->vert_end = crtc->vert_start + info->var.vsync_len; 12718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc->vert_total = crtc->vert_end + info->var.upper_margin; 12728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc->pixel_clock = PICOS2KHZ(info->var.pixclock) * 1000; 12748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc->refresh_rate = (u16)(100 * (crtc->pixel_clock / 12758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski (crtc->vert_total * crtc->horiz_total))); 12768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (info->var.vmode & FB_VMODE_DOUBLE) 12788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc->flags |= 0x1; 12798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (info->var.vmode & FB_VMODE_INTERLACED) 12808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc->flags |= 0x2; 12818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) 12828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc->flags |= 0x4; 12838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) 12848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc->flags |= 0x8; 12858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski memcpy(&par->crtc, crtc, sizeof(*crtc)); 12868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else { 12878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski memset(&par->crtc, 0, sizeof(*crtc)); 12888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 12898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.buf_len = sizeof(struct vbe_crtc_ib); 12918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->buf = &par->crtc; 12928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 12938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_exec(task); 12948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err || (task->t.regs.eax & 0xffff) != 0x004f) { 12958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 12968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * The mode switch might have failed because we tried to 12978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * use our own timings. Try again with the default timings. 12988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 12998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (crtc != NULL) { 13008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_WARNING "uvesafb: mode switch failed " 13018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "(eax=0x%x, err=%d). Trying again with " 13028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "default timings.\n", task->t.regs.eax, err); 13038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_reset(task); 13048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski kfree(crtc); 13058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski crtc = NULL; 13068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->var.pixclock = 0; 13078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski goto setmode; 13088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else { 13098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_ERR "uvesafb: mode switch failed (eax=" 13108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "0x%x, err=%d)\n", task->t.regs.eax, err); 13118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = -EINVAL; 13128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski goto out; 13138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 13148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 13158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->mode_idx = i; 13168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 13178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* For 8bpp modes, always try to set the DAC to 8 bits. */ 13188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_ib.capabilities & VBE_CAP_CAN_SWITCH_DAC && 13198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode->bits_per_pixel <= 8) { 13208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_reset(task); 13218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.eax = 0x4f08; 13228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.regs.ebx = 0x0800; 13238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 13248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_exec(task); 13258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err || (task->t.regs.eax & 0xffff) != 0x004f || 13268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ((task->t.regs.ebx & 0xff00) >> 8) != 8) { 13270ca1071f7dbd673de826eb3fb01bfdfd1d423433Michal Januszewski dac_width = 6; 13280ca1071f7dbd673de826eb3fb01bfdfd1d423433Michal Januszewski } else { 13290ca1071f7dbd673de826eb3fb01bfdfd1d423433Michal Januszewski dac_width = 8; 13308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 13318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 13328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 13338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->fix.visual = (info->var.bits_per_pixel == 8) ? 13348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 13358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->fix.line_length = mode->bytes_per_scan_line; 13368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 13378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskiout: if (crtc != NULL) 13388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski kfree(crtc); 13398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_free(task); 13408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 13418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return err; 13428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 13438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 13448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic void uvesafb_check_limits(struct fb_var_screeninfo *var, 13458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info) 13468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 13478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski const struct fb_videomode *mode; 13488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 13498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 13508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 13518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * If pixclock is set to 0, then we're using default BIOS timings 13528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * and thus don't have to perform any checks here. 13538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 13548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!var->pixclock) 13558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return; 13568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 13578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_ib.vbe_version < 0x0300) { 13588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, var, info); 13598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return; 13608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 13618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 13628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!fb_validate_mode(var, info)) 13638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return; 13648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 13658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode = fb_find_best_mode(var, &info->modelist); 13668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (mode) { 13678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (mode->xres == var->xres && mode->yres == var->yres && 13688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski !(mode->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE))) { 13698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_videomode_to_var(var, mode); 13708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return; 13718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 13728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 13738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 13748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (info->monspecs.gtf && !fb_get_mode(FB_MAXTIMINGS, 0, var, info)) 13758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return; 13768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Use default refresh rate */ 13778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->pixclock = 0; 13788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 13798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 13808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int uvesafb_check_var(struct fb_var_screeninfo *var, 13818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info) 13828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 13838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 13848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct vbe_mode_ib *mode = NULL; 13858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int match = -1; 13868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int depth = var->red.length + var->green.length + var->blue.length; 13878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 13888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 13898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Various apps will use bits_per_pixel to set the color depth, 13908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * which is theoretically incorrect, but which we'll try to handle 13918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * here. 13928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 13938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (depth == 0 || abs(depth - var->bits_per_pixel) >= 8) 13948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski depth = var->bits_per_pixel; 13958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 13968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski match = uvesafb_vbe_find_mode(par, var->xres, var->yres, depth, 13978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski UVESAFB_EXACT_RES); 13988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (match == -1) 13998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -EINVAL; 14008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 14018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode = &par->vbe_modes[match]; 14028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_setup_var(var, info, mode); 14038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 14048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 14058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Check whether we have remapped enough memory for this mode. 14068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * We might be called at an early stage, when we haven't remapped 14078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * any memory yet, in which case we simply skip the check. 14088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 14098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (var->yres * mode->bytes_per_scan_line > info->fix.smem_len 14108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski && info->fix.smem_len) 14118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -EINVAL; 14128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 14138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if ((var->vmode & FB_VMODE_DOUBLE) && 14148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski !(par->vbe_modes[match].mode_attr & 0x100)) 14158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->vmode &= ~FB_VMODE_DOUBLE; 14168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 14178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if ((var->vmode & FB_VMODE_INTERLACED) && 14188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski !(par->vbe_modes[match].mode_attr & 0x200)) 14198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->vmode &= ~FB_VMODE_INTERLACED; 14208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 14218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_check_limits(var, info); 14228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 14238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->xres_virtual = var->xres; 14248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->yres_virtual = (par->ypan) ? 14258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->fix.smem_len / mode->bytes_per_scan_line : 14268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski var->yres; 14278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 14288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 14298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 14308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic struct fb_ops uvesafb_ops = { 14318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .owner = THIS_MODULE, 14328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .fb_open = uvesafb_open, 14338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .fb_release = uvesafb_release, 14348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .fb_setcolreg = uvesafb_setcolreg, 14358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .fb_setcmap = uvesafb_setcmap, 14368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .fb_pan_display = uvesafb_pan_display, 14378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .fb_blank = uvesafb_blank, 14388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .fb_fillrect = cfb_fillrect, 14398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .fb_copyarea = cfb_copyarea, 14408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .fb_imageblit = cfb_imageblit, 14418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .fb_check_var = uvesafb_check_var, 14428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .fb_set_par = uvesafb_set_par, 14438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski}; 14448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 14458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic void __devinit uvesafb_init_info(struct fb_info *info, 14468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct vbe_mode_ib *mode) 14478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 14488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski unsigned int size_vmode; 14498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski unsigned int size_remap; 14508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski unsigned int size_total; 14518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 14528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int i, h; 14538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 14548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->pseudo_palette = ((u8 *)info->par + sizeof(struct uvesafb_par)); 14558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->fix = uvesafb_fix; 14568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->fix.ypanstep = par->ypan ? 1 : 0; 14578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->fix.ywrapstep = (par->ypan > 1) ? 1 : 0; 14588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 14598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Disable blanking if the user requested so. */ 14608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!blank) 14618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->fbops->fb_blank = NULL; 14628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 14638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 14648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * Find out how much IO memory is required for the mode with 14658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * the highest resolution. 14668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 14678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski size_remap = 0; 14688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski for (i = 0; i < par->vbe_modes_cnt; i++) { 14698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski h = par->vbe_modes[i].bytes_per_scan_line * 14708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->vbe_modes[i].y_res; 14718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (h > size_remap) 14728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski size_remap = h; 14738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 14748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski size_remap *= 2; 14758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 14768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 14778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * size_vmode -- that is the amount of memory needed for the 14788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * used video mode, i.e. the minimum amount of 14798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * memory we need. 14808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 14818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (mode != NULL) { 14828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski size_vmode = info->var.yres * mode->bytes_per_scan_line; 14838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else { 14848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski size_vmode = info->var.yres * info->var.xres * 14858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ((info->var.bits_per_pixel + 7) >> 3); 14868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 14878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 14888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 14898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * size_total -- all video memory we have. Used for mtrr 14908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * entries, resource allocation and bounds 14918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * checking. 14928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 14938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski size_total = par->vbe_ib.total_memory * 65536; 14948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (vram_total) 14958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski size_total = vram_total * 1024 * 1024; 14968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (size_total < size_vmode) 14978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski size_total = size_vmode; 14988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 14998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 15008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * size_remap -- the amount of video memory we are going to 15018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * use for vesafb. With modern cards it is no 15028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * option to simply use size_total as th 15038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * wastes plenty of kernel address space. 15048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 15058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (vram_remap) 15068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski size_remap = vram_remap * 1024 * 1024; 15078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (size_remap < size_vmode) 15088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski size_remap = size_vmode; 15098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (size_remap > size_total) 15108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski size_remap = size_total; 15118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 15128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->fix.smem_len = size_remap; 15138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->fix.smem_start = mode->phys_base_ptr; 15148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 15158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* 15168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * We have to set yres_virtual here because when setup_var() was 15178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski * called, smem_len wasn't defined yet. 15188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski */ 15198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->var.yres_virtual = info->fix.smem_len / 15208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode->bytes_per_scan_line; 15218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 15228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->ypan && info->var.yres_virtual > info->var.yres) { 15238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO "uvesafb: scrolling: %s " 15248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "using protected mode interface, " 15258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "yres_virtual=%d\n", 15268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski (par->ypan > 1) ? "ywrap" : "ypan", 15278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->var.yres_virtual); 15288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else { 15298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO "uvesafb: scrolling: redraw\n"); 15308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->var.yres_virtual = info->var.yres; 15318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->ypan = 0; 15328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 15338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 15348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->flags = FBINFO_FLAG_DEFAULT | 15351cc9fb6dbf915e5c7e7e59bb7fab10572ddbb349Roel Kluin (par->ypan ? FBINFO_HWACCEL_YPAN : 0); 15368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 15378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!par->ypan) 15388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->fbops->fb_pan_display = NULL; 15398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 15408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 154127b526a09086d563d61cf0e0fdd5c8e3f3c295d4Randy Dunlapstatic void __devinit uvesafb_init_mtrr(struct fb_info *info) 15428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 15438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#ifdef CONFIG_MTRR 15448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (mtrr && !(info->fix.smem_start & (PAGE_SIZE - 1))) { 15458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int temp_size = info->fix.smem_len; 15468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski unsigned int type = 0; 15478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 15488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski switch (mtrr) { 15498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski case 1: 15508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski type = MTRR_TYPE_UNCACHABLE; 15518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski break; 15528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski case 2: 15538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski type = MTRR_TYPE_WRBACK; 15548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski break; 15558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski case 3: 15568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski type = MTRR_TYPE_WRCOMB; 15578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski break; 15588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski case 4: 15598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski type = MTRR_TYPE_WRTHROUGH; 15608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski break; 15618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski default: 15628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski type = 0; 15638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski break; 15648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 15658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 15668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (type) { 15678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int rc; 15688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 15698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Find the largest power-of-two */ 1570803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter temp_size = roundup_pow_of_two(temp_size); 15718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 15728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski /* Try and find a power of two to add */ 15738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski do { 15748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski rc = mtrr_add(info->fix.smem_start, 15758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski temp_size, type, 1); 15768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski temp_size >>= 1; 15778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } while (temp_size >= PAGE_SIZE && rc == -EINVAL); 15788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 15798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 15808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#endif /* CONFIG_MTRR */ 15818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 15828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1583803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichterstatic void __devinit uvesafb_ioremap(struct fb_info *info) 1584803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter{ 1585803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter#ifdef CONFIG_X86 1586803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter switch (mtrr) { 1587803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter case 1: /* uncachable */ 1588803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter info->screen_base = ioremap_nocache(info->fix.smem_start, info->fix.smem_len); 1589803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter break; 1590803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter case 2: /* write-back */ 1591803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter info->screen_base = ioremap_cache(info->fix.smem_start, info->fix.smem_len); 1592803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter break; 1593803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter case 3: /* write-combining */ 1594803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter info->screen_base = ioremap_wc(info->fix.smem_start, info->fix.smem_len); 1595803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter break; 1596803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter case 4: /* write-through */ 1597803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter default: 1598803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); 1599803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter break; 1600803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter } 1601803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter#else 1602803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); 1603803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter#endif /* CONFIG_X86 */ 1604803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter} 16058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic ssize_t uvesafb_show_vbe_ver(struct device *dev, 16078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct device_attribute *attr, char *buf) 16088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 16098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); 16108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 16118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return snprintf(buf, PAGE_SIZE, "%.4x\n", par->vbe_ib.vbe_version); 16138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 16148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic DEVICE_ATTR(vbe_version, S_IRUGO, uvesafb_show_vbe_ver, NULL); 16168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic ssize_t uvesafb_show_vbe_modes(struct device *dev, 16188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct device_attribute *attr, char *buf) 16198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 16208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); 16218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 16228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int ret = 0, i; 16238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski for (i = 0; i < par->vbe_modes_cnt && ret < PAGE_SIZE; i++) { 16258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ret += snprintf(buf + ret, PAGE_SIZE - ret, 16268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "%dx%d-%d, 0x%.4x\n", 16278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->vbe_modes[i].x_res, par->vbe_modes[i].y_res, 16288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->vbe_modes[i].depth, par->vbe_modes[i].mode_id); 16298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 16308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return ret; 16328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 16338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic DEVICE_ATTR(vbe_modes, S_IRUGO, uvesafb_show_vbe_modes, NULL); 16358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic ssize_t uvesafb_show_vendor(struct device *dev, 16378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct device_attribute *attr, char *buf) 16388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 16398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); 16408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 16418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_ib.oem_vendor_name_ptr) 16438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return snprintf(buf, PAGE_SIZE, "%s\n", (char *) 16448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski (&par->vbe_ib) + par->vbe_ib.oem_vendor_name_ptr); 16458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else 16468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 16478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 16488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic DEVICE_ATTR(oem_vendor, S_IRUGO, uvesafb_show_vendor, NULL); 16508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic ssize_t uvesafb_show_product_name(struct device *dev, 16528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct device_attribute *attr, char *buf) 16538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 16548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); 16558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 16568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_ib.oem_product_name_ptr) 16588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return snprintf(buf, PAGE_SIZE, "%s\n", (char *) 16598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski (&par->vbe_ib) + par->vbe_ib.oem_product_name_ptr); 16608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else 16618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 16628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 16638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic DEVICE_ATTR(oem_product_name, S_IRUGO, uvesafb_show_product_name, NULL); 16658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic ssize_t uvesafb_show_product_rev(struct device *dev, 16678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct device_attribute *attr, char *buf) 16688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 16698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); 16708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 16718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_ib.oem_product_rev_ptr) 16738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return snprintf(buf, PAGE_SIZE, "%s\n", (char *) 16748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski (&par->vbe_ib) + par->vbe_ib.oem_product_rev_ptr); 16758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else 16768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 16778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 16788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic DEVICE_ATTR(oem_product_rev, S_IRUGO, uvesafb_show_product_rev, NULL); 16808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic ssize_t uvesafb_show_oem_string(struct device *dev, 16828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct device_attribute *attr, char *buf) 16838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 16848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); 16858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 16868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_ib.oem_string_ptr) 16888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return snprintf(buf, PAGE_SIZE, "%s\n", 16898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski (char *)(&par->vbe_ib) + par->vbe_ib.oem_string_ptr); 16908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else 16918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 16928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 16938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic DEVICE_ATTR(oem_string, S_IRUGO, uvesafb_show_oem_string, NULL); 16958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 16968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic ssize_t uvesafb_show_nocrtc(struct device *dev, 16978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct device_attribute *attr, char *buf) 16988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 16998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); 17008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 17018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 17028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return snprintf(buf, PAGE_SIZE, "%d\n", par->nocrtc); 17038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 17048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 17058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic ssize_t uvesafb_store_nocrtc(struct device *dev, 17068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct device_attribute *attr, const char *buf, size_t count) 17078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 17088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); 17098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 17108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 17118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (count > 0) { 17128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (buf[0] == '0') 17138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->nocrtc = 0; 17148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else 17158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->nocrtc = 1; 17168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 17178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return count; 17188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 17198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 17208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic DEVICE_ATTR(nocrtc, S_IRUGO | S_IWUSR, uvesafb_show_nocrtc, 17218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_store_nocrtc); 17228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 17238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic struct attribute *uvesafb_dev_attrs[] = { 17248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski &dev_attr_vbe_version.attr, 17258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski &dev_attr_vbe_modes.attr, 17268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski &dev_attr_oem_vendor.attr, 17278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski &dev_attr_oem_product_name.attr, 17288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski &dev_attr_oem_product_rev.attr, 17298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski &dev_attr_oem_string.attr, 17308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski &dev_attr_nocrtc.attr, 17318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski NULL, 17328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski}; 17338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 17348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic struct attribute_group uvesafb_dev_attgrp = { 17358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .name = NULL, 17368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .attrs = uvesafb_dev_attrs, 17378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski}; 17388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 17398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int __devinit uvesafb_probe(struct platform_device *dev) 17408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 17418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info; 17428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct vbe_mode_ib *mode = NULL; 17438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par; 17448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int err = 0, i; 17458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 17468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info = framebuffer_alloc(sizeof(*par) + sizeof(u32) * 256, &dev->dev); 17478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!info) 17488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -ENOMEM; 17498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 17508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par = info->par; 17518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 17528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = uvesafb_vbe_init(info); 17538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err) { 17548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_ERR "uvesafb: vbe_init() failed with %d\n", err); 17558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski goto out; 17568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 17578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 17588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->fbops = &uvesafb_ops; 17598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 17608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski i = uvesafb_vbe_init_mode(info); 17618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (i < 0) { 17628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = -EINVAL; 17638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski goto out; 17648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else { 17658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode = &par->vbe_modes[i]; 17668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 17678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 17688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { 17698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = -ENXIO; 17708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski goto out; 17718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 17728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 17738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_init_info(info, mode); 17748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1775803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter if (!request_region(0x3c0, 32, "uvesafb")) { 1776803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter printk(KERN_ERR "uvesafb: request region 0x3c0-0x3e0 failed\n"); 1777803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter err = -EIO; 1778803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter goto out_mode; 1779803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter } 1780803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter 17818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!request_mem_region(info->fix.smem_start, info->fix.smem_len, 17828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "uvesafb")) { 17838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_ERR "uvesafb: cannot reserve video memory at " 17848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "0x%lx\n", info->fix.smem_start); 17858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = -EIO; 1786803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter goto out_reg; 17878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 17888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 1789803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter uvesafb_init_mtrr(info); 1790803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter uvesafb_ioremap(info); 17918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 17928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!info->screen_base) { 17938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_ERR 17948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "uvesafb: abort, cannot ioremap 0x%x bytes of video " 17958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "memory at 0x%lx\n", 17968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->fix.smem_len, info->fix.smem_start); 17978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = -EIO; 17988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski goto out_mem; 17998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 18008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski platform_set_drvdata(dev, info); 18028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (register_framebuffer(info) < 0) { 18048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_ERR 18058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "uvesafb: failed to register framebuffer device\n"); 18068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = -EINVAL; 1807803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter goto out_unmap; 18088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 18098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO "uvesafb: framebuffer at 0x%lx, mapped to 0x%p, " 18118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "using %dk, total %dk\n", info->fix.smem_start, 18128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->screen_base, info->fix.smem_len/1024, 18138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski par->vbe_ib.total_memory * 64); 18148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, 18158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->fix.id); 18168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = sysfs_create_group(&dev->dev.kobj, &uvesafb_dev_attgrp); 18188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err != 0) 18198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_WARNING "fb%d: failed to register attributes\n", 18208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski info->node); 18218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 18238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskiout_unmap: 18258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski iounmap(info->screen_base); 18268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskiout_mem: 18278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski release_mem_region(info->fix.smem_start, info->fix.smem_len); 1828803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichterout_reg: 1829803a4e14a7dceaf01dbc0e02c0fdea2eba4c81b3Thomas Schlichter release_region(0x3c0, 32); 18308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskiout_mode: 18318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!list_empty(&info->modelist)) 18328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_destroy_modelist(&info->modelist); 18338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_destroy_modedb(info->monspecs.modedb); 18348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_dealloc_cmap(&info->cmap); 18358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskiout: 18368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_modes) 18378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski kfree(par->vbe_modes); 18388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski framebuffer_release(info); 18408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return err; 18418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 18428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int uvesafb_remove(struct platform_device *dev) 18448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 18458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct fb_info *info = platform_get_drvdata(dev); 18468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (info) { 18488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_par *par = info->par; 18498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski sysfs_remove_group(&dev->dev.kobj, &uvesafb_dev_attgrp); 18518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski unregister_framebuffer(info); 18528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski release_region(0x3c0, 32); 18538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski iounmap(info->screen_base); 18548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski release_mem_region(info->fix.smem_start, info->fix.smem_len); 18558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_destroy_modedb(info->monspecs.modedb); 18568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski fb_dealloc_cmap(&info->cmap); 18578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par) { 18598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_modes) 18608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski kfree(par->vbe_modes); 18618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_state_orig) 18628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski kfree(par->vbe_state_orig); 18638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (par->vbe_state_saved) 18648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski kfree(par->vbe_state_saved); 18658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 18668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski framebuffer_release(info); 18688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 18698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 18708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 18718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic struct platform_driver uvesafb_driver = { 18738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .probe = uvesafb_probe, 18748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .remove = uvesafb_remove, 18758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .driver = { 18768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski .name = "uvesafb", 18778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski }, 18788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski}; 18798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic struct platform_device *uvesafb_device; 18818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#ifndef MODULE 18838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int __devinit uvesafb_setup(char *options) 18848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 18858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski char *this_opt; 18868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!options || !*options) 18888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 18898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski while ((this_opt = strsep(&options, ",")) != NULL) { 18918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!*this_opt) continue; 18928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 18938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!strcmp(this_opt, "redraw")) 18948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ypan = 0; 18958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strcmp(this_opt, "ypan")) 18968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ypan = 1; 18978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strcmp(this_opt, "ywrap")) 18988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ypan = 2; 18998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strcmp(this_opt, "vgapal")) 19008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski pmi_setpal = 0; 19018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strcmp(this_opt, "pmipal")) 19028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski pmi_setpal = 1; 19038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strncmp(this_opt, "mtrr:", 5)) 19048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mtrr = simple_strtoul(this_opt+5, NULL, 0); 19058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strcmp(this_opt, "nomtrr")) 19068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mtrr = 0; 19078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strcmp(this_opt, "nocrtc")) 19088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski nocrtc = 1; 19098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strcmp(this_opt, "noedid")) 19108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski noedid = 1; 19118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strcmp(this_opt, "noblank")) 19128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski blank = 0; 19138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strncmp(this_opt, "vtotal:", 7)) 19148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski vram_total = simple_strtoul(this_opt + 7, NULL, 0); 19158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strncmp(this_opt, "vremap:", 7)) 19168bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski vram_remap = simple_strtoul(this_opt + 7, NULL, 0); 19178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strncmp(this_opt, "maxhf:", 6)) 19188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski maxhf = simple_strtoul(this_opt + 6, NULL, 0); 19198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strncmp(this_opt, "maxvf:", 6)) 19208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski maxvf = simple_strtoul(this_opt + 6, NULL, 0); 19218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strncmp(this_opt, "maxclk:", 7)) 19228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski maxclk = simple_strtoul(this_opt + 7, NULL, 0); 19238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strncmp(this_opt, "vbemode:", 8)) 19248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski vbemode = simple_strtoul(this_opt + 8, NULL, 0); 19258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (this_opt[0] >= '0' && this_opt[0] <= '9') { 19268bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski mode_option = this_opt; 19278bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } else { 19288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_WARNING 19298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "uvesafb: unrecognized option %s\n", this_opt); 19308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 19318bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 19328bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 19338bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 19348bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 19358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#endif /* !MODULE */ 19368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 19378bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic ssize_t show_v86d(struct device_driver *dev, char *buf) 19388bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 19398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return snprintf(buf, PAGE_SIZE, "%s\n", v86d_path); 19408bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 19418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 19428bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic ssize_t store_v86d(struct device_driver *dev, const char *buf, 19438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski size_t count) 19448bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 19458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski strncpy(v86d_path, buf, PATH_MAX); 19468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return count; 19478bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 19488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 19498bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic DRIVER_ATTR(v86d, S_IRUGO | S_IWUSR, show_v86d, store_v86d); 19508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 19518bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic int __devinit uvesafb_init(void) 19528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 19538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski int err; 19548bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 19558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#ifndef MODULE 19568bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski char *option = NULL; 19578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 19588bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (fb_get_options("uvesafb", &option)) 19598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return -ENODEV; 19608bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_setup(option); 19618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski#endif 19628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = cn_add_callback(&uvesafb_cn_id, "uvesafb", uvesafb_cn_callback); 19638bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err) 19648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return err; 19658bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 19668bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = platform_driver_register(&uvesafb_driver); 19678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 19688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!err) { 19698bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_device = platform_device_alloc("uvesafb", 0); 19708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (uvesafb_device) 19718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = platform_device_add(uvesafb_device); 19728bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else 19738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = -ENOMEM; 19748bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 19758bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err) { 19768bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski platform_device_put(uvesafb_device); 19778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski platform_driver_unregister(&uvesafb_driver); 19788bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski cn_del_callback(&uvesafb_cn_id); 19798bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return err; 19808bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 19818bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 19828bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = driver_create_file(&uvesafb_driver.driver, 19838bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski &driver_attr_v86d); 19848bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (err) { 19858bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski printk(KERN_WARNING "uvesafb: failed to register " 19868bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "attributes\n"); 19878bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski err = 0; 19888bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 19898bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 19908bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return err; 19918bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 19928bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 19938bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_init(uvesafb_init); 19948bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 19958bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskistatic void __devexit uvesafb_exit(void) 19968bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 19978bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski struct uvesafb_ktask *task; 19988bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 19998bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (v86d_started) { 20008bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task = uvesafb_prep(); 20018bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (task) { 20028bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski task->t.flags = TF_EXIT; 20038bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_exec(task); 20048bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski uvesafb_free(task); 20058bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 20068bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski } 20078bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 20088bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski cn_del_callback(&uvesafb_cn_id); 20098bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski driver_remove_file(&uvesafb_driver.driver, &driver_attr_v86d); 20108bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski platform_device_unregister(uvesafb_device); 20118bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski platform_driver_unregister(&uvesafb_driver); 20128bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 20138bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 20148bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_exit(uvesafb_exit); 20158bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 20169bbb9e5a33109b2832e2e63dcc7a132924ab374bRusty Russellstatic int param_set_scroll(const char *val, const struct kernel_param *kp) 20178bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski{ 20188bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ypan = 0; 20198bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 20208bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski if (!strcmp(val, "redraw")) 20218bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ypan = 0; 20228bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strcmp(val, "ypan")) 20238bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ypan = 1; 20248bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski else if (!strcmp(val, "ywrap")) 20258bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski ypan = 2; 20262ead9439f0c6ed03faafe27abe8bc1dd256d117bRusty Russell else 20272ead9439f0c6ed03faafe27abe8bc1dd256d117bRusty Russell return -EINVAL; 20288bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 20298bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski return 0; 20308bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski} 20319bbb9e5a33109b2832e2e63dcc7a132924ab374bRusty Russellstatic struct kernel_param_ops param_ops_scroll = { 20329bbb9e5a33109b2832e2e63dcc7a132924ab374bRusty Russell .set = param_set_scroll, 20339bbb9e5a33109b2832e2e63dcc7a132924ab374bRusty Russell}; 20345eb03a4ab239d8769fa13df6c894d618ecae1b50Randy Dunlap#define param_check_scroll(name, p) __param_check(name, p, void) 20358bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 20368bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_param_named(scroll, ypan, scroll, 0); 20378bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_PARM_DESC(scroll, 20385eb03a4ab239d8769fa13df6c894d618ecae1b50Randy Dunlap "Scrolling mode, set to 'redraw', 'ypan', or 'ywrap'"); 20398bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_param_named(vgapal, pmi_setpal, invbool, 0); 20408bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_PARM_DESC(vgapal, "Set palette using VGA registers"); 20418bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_param_named(pmipal, pmi_setpal, bool, 0); 20428bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_PARM_DESC(pmipal, "Set palette using PMI calls"); 20438bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_param(mtrr, uint, 0); 20448bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_PARM_DESC(mtrr, 20458bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "Memory Type Range Registers setting. Use 0 to disable."); 20468bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_param(blank, bool, 0); 20478bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_PARM_DESC(blank, "Enable hardware blanking"); 20488bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_param(nocrtc, bool, 0); 20498bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_PARM_DESC(nocrtc, "Ignore CRTC timings when setting modes"); 20508bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_param(noedid, bool, 0); 20518bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_PARM_DESC(noedid, 20528bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "Ignore EDID-provided monitor limits when setting modes"); 20538bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_param(vram_remap, uint, 0); 20548bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_PARM_DESC(vram_remap, "Set amount of video memory to be used [MiB]"); 20558bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_param(vram_total, uint, 0); 20568bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_PARM_DESC(vram_total, "Set total amount of video memoery [MiB]"); 20578bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_param(maxclk, ushort, 0); 20588bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_PARM_DESC(maxclk, "Maximum pixelclock [MHz], overrides EDID data"); 20598bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_param(maxhf, ushort, 0); 20608bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_PARM_DESC(maxhf, 20618bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "Maximum horizontal frequency [kHz], overrides EDID data"); 20628bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_param(maxvf, ushort, 0); 20638bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_PARM_DESC(maxvf, 20648bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "Maximum vertical frequency [Hz], overrides EDID data"); 2065012e26096b36bfeacaba2c9e31eaf32d6faa6567Krzysztof Heltmodule_param(mode_option, charp, 0); 2066012e26096b36bfeacaba2c9e31eaf32d6faa6567Krzysztof HeltMODULE_PARM_DESC(mode_option, 20678bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "Specify initial video mode as \"<xres>x<yres>[-<bpp>][@<refresh>]\""); 20688bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_param(vbemode, ushort, 0); 20698bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_PARM_DESC(vbemode, 20708bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski "VBE mode number to set, overrides the 'mode' option"); 20718bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewskimodule_param_string(v86d, v86d_path, PATH_MAX, 0660); 20728bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_PARM_DESC(v86d, "Path to the v86d userspace helper."); 20738bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 20748bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_LICENSE("GPL"); 20758bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_AUTHOR("Michal Januszewski <spock@gentoo.org>"); 20768bdb3a2d7df48b861972c4bfb58490853a228f51Michal JanuszewskiMODULE_DESCRIPTION("Framebuffer driver for VBE2.0+ compliant graphics boards"); 20778bdb3a2d7df48b861972c4bfb58490853a228f51Michal Januszewski 2078