static int open_display(struct omap_display_device *display, enum omap_display_feature features) { int i; DBG_PRINT("Opening display '%s'", display->name); /* TODO: Support horizontal orientation */ if (features & ORIENTATION_HORIZONTAL) { DBG_PRINT("Horizontal orientation is not supported yet , " "falling back to vertical orientation"); features = ORIENTATION_VERTICAL; } display->features = features; display->reference_count++; for (i = 0; i < display->overlay_managers_count; i++) omap_dss_get_device(display->overlay_managers[i]->device); /* If the main buffer doesn't exist create it */ if (!display->main_buffer) { DBG_PRINT("Main buffer doesn't exist for display '%s', create" " one", display->name); display->main_buffer = create_main_buffer(display); if (!display->main_buffer) { ERR_PRINT("Failed to create main buffer for '%s'", display->name); return 1; } } return 0; }
/* initialize connector */ struct drm_connector *omap_connector_init(struct drm_device *dev, int connector_type, struct omap_dss_device *dssdev, struct drm_encoder *encoder) { struct drm_connector *connector = NULL; struct omap_connector *omap_connector; DBG("%s", dssdev->name); omap_dss_get_device(dssdev); omap_connector = kzalloc(sizeof(struct omap_connector), GFP_KERNEL); if (!omap_connector) { dev_err(dev->dev, "could not allocate connector\n"); goto fail; } omap_connector->dssdev = dssdev; omap_connector->encoder = encoder; connector = &omap_connector->base; drm_connector_init(dev, connector, &omap_connector_funcs, connector_type); drm_connector_helper_add(connector, &omap_connector_helper_funcs); #if 0 /* enable when dss2 supports hotplug */ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_HPD) connector->polled = 0; else #endif connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; connector->interlace_allowed = 1; connector->doublescan_allowed = 0; drm_sysfs_connector_add(connector); return connector; fail: if (connector) omap_connector_destroy(connector); return NULL; }
/* * ref count of the found device is incremented. * ref count of from-device is decremented. */ struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from) { struct list_head *l; struct omap_dss_device *dssdev; mutex_lock(&panel_list_mutex); if (list_empty(&panel_list)) { dssdev = NULL; goto out; } if (from == NULL) { dssdev = list_first_entry(&panel_list, struct omap_dss_device, panel_list); omap_dss_get_device(dssdev); goto out; }
/* * Function is called when the video module hardwrae is physically removed */ void bmi_video_remove(struct bmi_device *bdev) { int irq; int i; int slot; struct bmi_video *video; struct class *bmi_class; static struct omap_dss_device *dssdev; printk(KERN_DEBUG "bmi_video: Module Removed...\n"); //Would turn LED red, but we can't trust the HW is connected still slot = bdev->slot->slotnum; video = &g_bmi_video; //removals have known unwind errors iff rmmod bmi_video_core while //device is plugged in device_remove_file(&bdev->dev, &dev_attr_vmode); device_remove_file(&bdev->dev, &dev_attr_vga_edid); device_remove_file(&bdev->dev, &dev_attr_dvi_edid); bmi_class = bmi_get_class (); device_destroy (bmi_class, MKDEV(major, slot)); // -- disable displays monitors_off_safe(video);//safe for missing HW // -- disable all displays for_each_dss_dev(dssdev) { omap_dss_get_device(dssdev); if (dssdev->state) dssdev->driver->disable(dssdev); } if(video->swap_eeprom){ //we are just 'borrowing' this pointer, //do not unregister! see bmi_video_probe. video->swap_eeprom = NULL; video->swap_eeprom_state = OFF; } if(video->eeprom_switch) { i2c_unregister_device(video->eeprom_switch); video->eeprom_switch = NULL; } if(video->gpio_controller) { //dbg_unexport_gpios_to_sysfs(); gpio_free_array(vid_gpios, ARRAY_SIZE(vid_gpios)); i2c_unregister_device(video->gpio_controller); video->gpio_controller= NULL; } if(video->dvi_controller) { i2c_unregister_device(video->dvi_controller); video->dvi_controller = NULL; } printk(KERN_INFO "bmi_video: 9\n"); if(video->vga_controller) { i2c_unregister_device(video->vga_controller); video->vga_controller = NULL; } irq = bdev->slot->status_irq; // -- legacy vodoo code. Left in for safety for (i = 0; i < 4; i++) bmi_slot_gpio_direction_in(slot, i); if (video->vga_monitor_edid) { kfree(video->vga_monitor_edid); //created by a library. we must free video->vga_monitor_edid = NULL; } if (video->dvi_monitor_edid) { kfree(video->dvi_monitor_edid); //created by a library. we must free video->dvi_monitor_edid = NULL; } //just in case, clear the global g_dvi_disp = NULL; g_vga_disp = NULL; video->class_dev = 0; // de-attach driver-specific struct from bmi_device structure bmi_device_set_drvdata (bdev, 0); video->bdev = 0; printk(KERN_INFO "bmi_video_remove done "); return; //Clean, squeaky clean }
// probe - insert PIM int bmi_video_probe(struct bmi_device *bdev) { int err = 0; int slot; int irq; struct bmi_video *video; struct class *bmi_class; struct i2c_adapter *adap; struct omap_dss_device *dssdev; printk (KERN_INFO "bmi_video.c: probe...\n"); slot = bdev->slot->slotnum; adap = bdev->slot->adap; video = &g_bmi_video; video->dvi_monitor_edid = NULL; video->vga_monitor_edid = NULL; video->bdev = 0; dssdev = NULL; g_dvi_disp = NULL; g_vga_disp = NULL; /* disable all video devices, store vga/dvi entries */ for_each_dss_dev(dssdev) { omap_dss_get_device(dssdev); if (dssdev->state) dssdev->driver->disable(dssdev); // our dss names are from buglabs board files if (strnicmp(dssdev->name, "dvi", 3) == 0) g_dvi_disp = dssdev; else if (strnicmp(dssdev->name, "vga", 3) == 0) g_vga_disp = dssdev; } // bind driver and bmi_device video->bdev = bdev; // create class device bmi_class = bmi_get_class(); // -- grab eeprom addr if(bdev->slot->eeprom) { video->swap_eeprom = bdev->slot->eeprom; video->swap_eeprom_state = OFF; //set to read bmi board eeprom //printk(KERN_ERR "swizzling slot eeprom, addr %x", // (unsigned int)video->swap_eeprom->addr); } else { printk(KERN_ERR "module eeprom is null. Module type is impossible"); video->swap_eeprom = 0x00; video->swap_eeprom_state = OFF; } // -- grap i2c expander switch video->eeprom_switch = i2c_new_device(adap, &i2cswitch_info); if(video->eeprom_switch == NULL) { printk(KERN_ERR "i2c addr %x fail", i2cswitch_info.addr); err = -ENOTTY; goto probe_fail1; } // -- grab i2c gpio chip and set it up if (gpio_is_valid(VIDEO_GPIO_BASE)) video->gpio_controller = i2c_new_device(adap,&gpio_controller_info); else { printk(KERN_ERR "i2c addr %x in use", VIDEO_GPIO_BASE); err = -ENOTTY; goto probe_fail2; } if(video->gpio_controller == NULL) { printk(KERN_ERR "i2c addr %x fail", gpio_controller_info.addr); err = -ENOTTY; goto probe_fail2; } err = gpio_request_array(vid_gpios, ARRAY_SIZE(vid_gpios)); if (err) { printk(KERN_ERR "GPIO's not requestable. Damm"); err = -ENOTTY; goto probe_fail3; } //dbg_export_gpios_to_sysfs(); //we have gpio's now, turn the LED to red since we are not initalized bmi_video_ledset(VIDEO_LED_RED); // -- grab i2c for the dvi controller video->dvi_controller = i2c_new_device(adap, &tfp_info); if (video->dvi_controller == NULL){ printk(KERN_ERR "DVI monitor controller not found\n"); err = -ENOTTY; goto probe_fail4; } video->vga_controller = i2c_new_device(adap, &ths_info); if (video->vga_controller == NULL) { printk(KERN_ERR "VGA monitor controller not found\n"); err = -ENOTTY; goto probe_fail5; } //FUTURE: enable pulg event interrupt for GPIO //ths_info.irq = gpio_to_irq(DVI_MONITOR_SENSE_GPIO); // -- to get ths8201 on the bus OK, we need to do a reset cycle ths8200_disable(video->vga_controller);//TRICKY: does some setup -> //didn't have time to debug why this works and 'init' doesn't ths8200_standby(VGA_RESET_GPIO); err = device_create_file(&bdev->dev, &dev_attr_vmode); if (err < 0) printk(KERN_ERR "Error creating SYSFS entries...\n"); //TRCIKY: don't exit on this error, tolerate it err = scan_for_monitors(AUTO, video); //based on monitor's found, choose the best' if(video->dvi_monitor_edid) { printk(KERN_INFO "dvi monitor detected"); enable_dvi(video); } else if(video->vga_monitor_edid) { printk(KERN_INFO "vga monitor detected"); enable_vga(video); } else { printk(KERN_ERR "no monitor detected"); monitors_off(video); } err = device_create_file(&bdev->dev, &dev_attr_vga_edid); if (err < 0) printk(KERN_ERR "Error creating SYSFS entries...\n"); //TRCIKY: don't exit on this error, tolerate it err = device_create_file(&bdev->dev, &dev_attr_dvi_edid); if (err < 0) printk(KERN_ERR "Error creating SYSFS entries...\n"); //TRCIKY: don't exit on this error, tolerate it //request PIM interrupt irq = bdev->slot->status_irq; sprintf (video->int_name, "bmi_video%d", slot); bmi_device_set_drvdata (bdev, video); // -- successfuly loaded, even if not everyting is perfect return 0; // -- failure/error cleanup probe_fail5: if(video->dvi_controller) { i2c_unregister_device(video->dvi_controller); video->dvi_controller = NULL; } probe_fail4: //dbg_unexport_gpios_to_sysfs(); probe_fail3: if(video->gpio_controller) { i2c_unregister_device(video->gpio_controller); video->gpio_controller = NULL; } probe_fail2: if(video->eeprom_switch) { i2c_unregister_device(video->eeprom_switch); video->eeprom_switch = NULL; } probe_fail1: video->swap_eeprom = 0x00; video->swap_eeprom_state = OFF; return err; }
static __devinit int omap_hdmi_probe(struct platform_device *pdev) { int ret; struct resource *hdmi_rsrc; struct omap_dss_device *dssdev = NULL; bool hdmi_dev_found = false; hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!hdmi_rsrc) { dev_err(&pdev->dev, "Cannot obtain IORESOURCE_MEM HDMI\n"); return -ENODEV; } omap_hdmi_dai_dma_params.port_addr = hdmi_rsrc->start + OMAP_HDMI_AUDIO_DMA_PORT; hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (!hdmi_rsrc) { dev_err(&pdev->dev, "Cannot obtain IORESOURCE_DMA HDMI\n"); return -ENODEV; } hdmi.oh = omap_hwmod_lookup("dss_hdmi"); if (!hdmi.oh) { dev_err(&pdev->dev, "can't find omap_hwmod for hdmi\n"); return -ENODEV; } omap_hdmi_dai_dma_params.dma_req = hdmi_rsrc->start; /* * Find an HDMI device. In the future, registers all the HDMI devices * it finds and create a PCM for each. */ for_each_dss_dev(dssdev) { omap_dss_get_device(dssdev); if (!dssdev->driver) { omap_dss_put_device(dssdev); continue; } if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { hdmi_dev_found = true; break; } } if (!hdmi_dev_found) { dev_err(&pdev->dev, "no driver for HDMI display found"); return -ENODEV; } hdmi.dssdev = dssdev; /* the supported rates and sample format depend on the cpu */ if (cpu_is_omap44xx()) { omap_hdmi_dai.playback.rates = OMAP4_HDMI_RATES; omap_hdmi_dai.playback.formats = OMAP4_HDMI_FORMATS; omap_hdmi_dai.playback.channels_max = 8; } else { /* OMAP5 */ omap_hdmi_dai.playback.rates = OMAP5_HDMI_RATES; omap_hdmi_dai.playback.formats = OMAP5_HDMI_FORMATS; #ifdef CONFIG_ARCH_OMAP5_ES1 omap_hdmi_dai.playback.channels_max = 2; #else omap_hdmi_dai.playback.channels_max = 8; #endif } ret = snd_soc_register_dai(&pdev->dev, &omap_hdmi_dai); hdmi.notifier.notifier_call = hdmi_audio_notifier_callback; blocking_notifier_chain_register(&hdmi.dssdev->state_notifiers, &hdmi.notifier); return ret; }