diff --git a/geofield.widgets.inc b/geofield.widgets.inc
index e86eaa0..89c64f7 100644
--- a/geofield.widgets.inc
+++ b/geofield.widgets.inc
@@ -91,6 +91,42 @@ function geofield_field_widget_settings_form($field, $instance) {
       ),
       '#default_value' => (isset($settings['data_storage'])) ? $settings['data_storage'] : 'collection',
     );
+
+    // Add optional Geocoder support.
+    $use_geocoder = isset($settings['use_geocoder']) ? $settings['use_geocoder'] : 0;
+    $geocoder_form = array(
+      '#type' => 'fieldset',
+      '#title' => t('Geocoder settings'),
+    );
+    if (module_exists('geocoder')) {
+      $geocoder_form['use_geocoder'] = array(
+        '#type' => 'checkbox',
+        '#title' => t('Enable geocoding of location data (best when used with an address field)'),
+        '#default_value' => $use_geocoder,
+      );
+      module_load_include('inc', 'geocoder', 'geocoder.widget');
+      $new = geocoder_field_widget_settings_form($field, $instance);
+      $geocoder_keys = element_children($new);
+      // Show the geocoder fields only if geocoder is selected.
+      foreach (element_children($new) as $key) {
+        $new[$key]['#required'] = FALSE;
+        // Don't override any existing #states settings.
+        if (!isset($new[$key]['#states'])) {
+          $new[$key]['#states'] = array();
+        }
+        if (!isset($new[$key]['#states']['visible'])) {
+          $new[$key]['#states']['visible'] = array();
+        }
+        $new[$key]['#states']['visible'][':input[name="instance[widget][settings][use_geocoder]"]'] = array('checked' => TRUE);
+      }
+      $geocoder_form += $new;
+    }
+    else {
+      $geocoder_form['add_geocoder'] = array(
+        '#markup' => t('Optionally, install the <a href="http//drupal.org/project/geocoder">Geocoder</a> module and add an <a href="http://drupal.org/project/addressfield">Address field</a> to enable mapping by address.'),
+      );
+    }
+    $form += $geocoder_form;
   }
   return $form;
 }
@@ -201,6 +237,33 @@ function geofield_field_widget_form(&$form, &$form_state, $field, $instance,
   }
 
   if ($widget['type'] == 'geofield_openlayers') {
+    if (!empty($settings['use_geocoder']) && !empty($settings['geocoder_field'])) {
+      if ($field = field_info_instance($instance['entity_type'], $settings['geocoder_field'], $instance['bundle'])) {
+        $label = $field['label'];
+      }
+      else {
+        switch ($settings['geocoder_field']) {
+          case 'title':
+            $label = t('Title');
+            break;
+          case 'name':
+            $label = t('Name');
+            break;
+          default:
+            $label = $settings['geocoder_field'];
+        }
+      }
+      $element['use_geocoder'] = array(
+        '#type' => 'submit',
+        '#value' => t('Geocode from !field field', array('!field' => $label)),
+        '#ajax' => array(
+          'callback' => 'geofield_widget_geocode',
+          'wrapper' => 'edit-field-geolocation',
+          'effect' => 'fade',
+        ),
+      );
+    }
+
     $openlayers_map_id = !empty($instance['widget']['settings']['openlayers_map']) ? $instance['widget']['settings']['openlayers_map'] : 'geofield_widget_map';
     $element['#openlayers_mapname'] = $openlayers_map_id;
     $element['#after_build']= array('geofield_widget_openlayers_afterbuild');
@@ -210,6 +273,18 @@ function geofield_field_widget_form(&$form, &$form_state, $field, $instance,
 }
 
 /**
+ * Returns changed form.
+ *
+ * @see geofield_field_widget_form()
+ */
+function geofield_widget_geocode($form, $form_state) {
+  if (isset($form_state['clicked_button']) && end($form_state['clicked_button']['#parents']) == 'use_geocoder') {
+    $field_name = reset($form_state['clicked_button']['#parents']);
+    return $form[$field_name];
+  }
+}
+
+/**
  * Callback for afterbuild for widget for js addition to
  */
 
@@ -355,6 +430,19 @@ function geofield_element_validate($element, &$form_state) {
     }
   }
 
+  // If the use_geocoder button was clicked, set values with geocoder.
+  if (isset($form_state['clicked_button']) && end($form_state['clicked_button']['#parents']) == 'use_geocoder') {
+    $field_instance = field_info_instance($element['#entity_type'], $element['#field_name'], $element['#bundle']);
+    // We need the submitted values rather than the unaltered entity.
+    $entity = (object) $form_state['values'];
+    if ($field_value = geocoder_widget_get_field_value($element['#entity_type'], $entity, $field_instance)) {
+      $values = reset($field_value[LANGUAGE_NONE]);
+    }
+    else {
+      drupal_set_message(t('No location found.'));
+    }
+  }
+
   if ($geo_process == "PROCESS") {
     geofield_compute_values($values, $master_column);
 
