r600显卡中断注册:
r600_init
|--r600_startup
|--radeon_irq_kms_init
| |--drm_irq_install(rdev->ddev, rdev->ddev->pdev->irq);\\使用pci设备的中断号
| | \--ret = request_irq(irq, dev->driver->irq_handler,sh_flags, dev->driver->name, dev);
\\dev->driver->irq_handler指向radeon_driver_irq_handler_kms
r600显卡中断处理:
r600_irq_process \\r600系列显卡中断处理
\--while (rptr != wptr) { \\中断缓冲区数据处理
| \--switch (src_id) { \\处理显卡中断不同类型的事件
\--...
\--case 19: /* HPD/DAC hotplug */ \\处理显卡hpd插拔中断事件
| | \--switch (src_data) { \\hpd插拔中断事件中不同类型的hpd信号HPD0\1\2...
| | | \--case 0:
| | | \--rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD1_INTERRUPT;\\
| | | \--queue_hotplug = true;\\hotplug工作队列标记置真
| | | \--break;
| | | \--...
| | \--}
| \--}
|--} \\中断缓冲区数据全部处理完毕
\--if (queue_hotplug) \\queue_hotplug为真则提交任务到hotplug工作队列
| \--schedule_delayed_work(&rdev->hotplug_work, 0);
\--}
r600显卡hotplug_work工作队列初始化:
r600_init
|--r600_startup
|--radeon_irq_kms_init
| \--INIT_DELAYED_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
hotplug_work工作队列处理:
radeon_hotplug_work_func\\hotplug_work工作队列处理函数
\--...
\--list_for_each_entry(connector, &mode_config->connector_list, head) \\遍历每个connecter
| |--radeon_connector_hotplug(connector);\\处理单个drm_connector的热插拔
| | \--if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {..}\\DisplayPort特殊处理
| | \--if (radeon_connector->hpd.hpd==RADEON_HPD_NONE) return;\\VGA, TV接口无hpd管脚,不处理
| | |--radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);\\hook,指向r600_hpd_set_polarity
| | \--r600_hpd_set_polarity(rdev, radeon_connector->hpd.hpd)\\根据radeon_hpd_id类型读写显卡寄存器
| | | \--bool connected = r600_hpd_sense(rdev, hpd)\\根据radeon_hpd_id类型读状态寄存器 DC_HPD1_INT_STATUS & DC_HPDx_SENSE
| | | \--tmp = RREG32(DC_HPD1_INT_CONTROL);\\读控制寄存器DC_HPD1_INT_CONTROL存入tmp
| | | \--if (connected) tmp &= ~DC_HPDx_INT_POLARITY;\\根据状态寄存器connected ,修改tmp
| | | \--WREG32(DC_HPD1_INT_CONTROL, tmp);\\写控制寄存器
| | \..
| |--\\完成处理单个drm_connector处理,读状态寄存器,根据连接写控制寄存器
\--drm_helper_hpd_irq_event(dev);\\探测connector连接状态是否改变,发送热插拔uevent通知用户空间
| \--drm_for_each_connector_iter(connector, &conn_iter) \\遍历每个connetor
| | \--old_status = connector->status;\\保存当前连接状态
| | |--connector->status = drm_helper_probe_detect-->drm_helper_probe_detect_ctx\\执行新的连接状态探测
| | | \--ret = connector->funcs->detect(connector, force);\\r600 hdmi接口类型指向radeon_dvi_detect
| | | | |--radeon_dvi_detect(struct drm_connector *connector, bool force)
| | | \--return ret;\\返回新探测的连接状态
| | \--if (old_status != connector->status) changed = true;\\标记连接状态改变
| | \--if (changed)\\如果连接状态改变
| | | |--drm_kms_helper_hotplug_event
| | | | |--drm_sysfs_hotplug_event\\生成DRM uevent
| | | | |--dev->mode_config.funcs->output_poll_changed(dev);\\调用fbdev,指向 |--drm_fb_helper_output_poll_changed
| | | | | |--drm_fb_helper_hotplug_event