drm/radeon/kms: expose thermal/fan i2c buses
Alex Deucher [Thu, 11 Mar 2010 15:01:17 +0000 (10:01 -0500)]
Look up i2c bus in the power table and expose it.
You'll need to load a hwmon driver for any chips
on the bus, this patch just exposes the bus.

Signed-off-by: Alex Deucher <alexdeucher@gmail.com>

13 files changed:
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv770.c

index 9d6283e..db78d93 100644 (file)
@@ -747,6 +747,7 @@ int evergreen_init(struct radeon_device *rdev)
 
 void evergreen_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        evergreen_suspend(rdev);
 #if 0
        r600_blit_fini(rdev);
index ea5ebfe..9d634c8 100644 (file)
@@ -3443,6 +3443,7 @@ int r100_suspend(struct radeon_device *rdev)
 
 void r100_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
index 1042cea..6d75f81 100644 (file)
@@ -1335,6 +1335,7 @@ int r300_suspend(struct radeon_device *rdev)
 
 void r300_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
index 2ab35ff..0b8603c 100644 (file)
@@ -267,6 +267,7 @@ int r420_suspend(struct radeon_device *rdev)
 
 void r420_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
index 5b00d5e..5aee7fe 100644 (file)
@@ -2120,6 +2120,7 @@ int r600_init(struct radeon_device *rdev)
 
 void r600_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r600_audio_fini(rdev);
        r600_blit_fini(rdev);
        r600_cp_fini(rdev);
index bd63f53..46bfff9 100644 (file)
@@ -168,6 +168,7 @@ struct radeon_clock {
  * Power management
  */
 int radeon_pm_init(struct radeon_device *rdev);
+void radeon_pm_fini(struct radeon_device *rdev);
 void radeon_pm_compute_clocks(struct radeon_device *rdev);
 void radeon_combios_get_power_modes(struct radeon_device *rdev);
 void radeon_atombios_get_power_modes(struct radeon_device *rdev);
@@ -708,6 +709,7 @@ struct radeon_pm {
        struct radeon_power_state *requested_power_state;
        struct radeon_pm_clock_info *requested_clock_mode;
        struct radeon_power_state *default_power_state;
+       struct radeon_i2c_chan *i2c_bus;
 };
 
 
index e4540b2..815116e 100644 (file)
@@ -1461,6 +1461,30 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
        return tv_dac;
 }
 
+static const char *thermal_controller_names[] = {
+       "NONE",
+       "LM63",
+       "ADM1032",
+       "ADM1030",
+       "MUA6649",
+       "LM64",
+       "F75375",
+       "ASC7512",
+};
+
+static const char *pp_lib_thermal_controller_names[] = {
+       "NONE",
+       "LM63",
+       "ADM1032",
+       "ADM1030",
+       "MUA6649",
+       "LM64",
+       "F75375",
+       "RV6xx",
+       "RV770",
+       "ADT7473",
+};
+
 union power_info {
        struct _ATOM_POWERPLAY_INFO info;
        struct _ATOM_POWERPLAY_INFO_V2 info_2;
@@ -1480,6 +1504,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
        struct _ATOM_PPLIB_STATE *power_state;
        int num_modes = 0, i, j;
        int state_index = 0, mode_index = 0;
+       struct radeon_i2c_bus_rec i2c_bus;
 
        atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
 
@@ -1489,6 +1514,14 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
 
        if (power_info) {
                if (frev < 4) {
+                       /* add the i2c bus for thermal/fan chip */
+                       if (power_info->info.ucOverdriveThermalController > 0) {
+                               DRM_INFO("Possible %s thermal controller at 0x%02x\n",
+                                        thermal_controller_names[power_info->info.ucOverdriveThermalController],
+                                        power_info->info.ucOverdriveControllerAddress >> 1);
+                               i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine);
+                               rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal");
+                       }
                        num_modes = power_info->info.ucNumOfPowerModeEntries;
                        if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
                                num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
@@ -1698,6 +1731,24 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                }
                        }
                } else if (frev == 4) {
+                       /* add the i2c bus for thermal/fan chip */
+                       /* no support for internal controller yet */
+                       if (power_info->info_4.sThermalController.ucType > 0) {
+                               if ((power_info->info_4.sThermalController.ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) &&
+                                   (power_info->info_4.sThermalController.ucType == ATOM_PP_THERMALCONTROLLER_RV770)) {
+                                       DRM_INFO("Internal thermal controller %s fan control\n",
+                                                (power_info->info_4.sThermalController.ucFanParameters &
+                                                 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+                               } else {
+                                       DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
+                                                pp_lib_thermal_controller_names[power_info->info_4.sThermalController.ucType],
+                                                power_info->info_4.sThermalController.ucI2cAddress >> 1,
+                                                (power_info->info_4.sThermalController.ucFanParameters &
+                                                 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+                                       i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info_4.sThermalController.ucI2cLine);
+                                       rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal");
+                               }
+                       }
                        for (i = 0; i < power_info->info_4.ucNumStates; i++) {
                                mode_index = 0;
                                power_state = (struct _ATOM_PPLIB_STATE *)
index 4f37b52..6458d52 100644 (file)
@@ -257,6 +257,12 @@ int radeon_pm_init(struct radeon_device *rdev)
        return 0;
 }
 
+void radeon_pm_fini(struct radeon_device *rdev)
+{
+       if (rdev->pm.i2c_bus)
+               radeon_i2c_destroy(rdev->pm.i2c_bus);
+}
+
 void radeon_pm_compute_clocks(struct radeon_device *rdev)
 {
        struct drm_device *ddev = rdev->ddev;
index 1240e7d..850a90c 100644 (file)
@@ -454,6 +454,7 @@ int rs400_suspend(struct radeon_device *rdev)
 
 void rs400_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
index e3410c9..3630c16 100644 (file)
@@ -601,6 +601,7 @@ int rs600_suspend(struct radeon_device *rdev)
 
 void rs600_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
index c39cb50..6c92ae3 100644 (file)
@@ -658,6 +658,7 @@ int rs690_suspend(struct radeon_device *rdev)
 
 void rs690_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
index 26108b4..f85499f 100644 (file)
@@ -540,6 +540,7 @@ void rv515_set_safe_registers(struct radeon_device *rdev)
 
 void rv515_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
index 1484d06..2f917db 100644 (file)
@@ -1165,6 +1165,7 @@ int rv770_init(struct radeon_device *rdev)
 
 void rv770_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r600_blit_fini(rdev);
        r600_cp_fini(rdev);
        r600_wb_fini(rdev);